Skip to content

Commit

Permalink
P2321R2 zip: Make tuple, pair, and vector<bool>::reference `ind…
Browse files Browse the repository at this point in the history
…irectly_writable` (#2687)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
  • Loading branch information
cpplearner and StephanTLavavej authored May 5, 2022
1 parent 0a618df commit f8748eb
Show file tree
Hide file tree
Showing 13 changed files with 744 additions and 43 deletions.
258 changes: 223 additions & 35 deletions stl/inc/tuple

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,14 @@ struct is_assignable : bool_constant<__is_assignable(_To, _From)> {}; // determi
template <class _To, class _From>
_INLINE_VAR constexpr bool is_assignable_v = __is_assignable(_To, _From);

#if defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__)
template <class _To, class _From>
struct _Is_assignable_no_precondition_check : bool_constant<__is_assignable_no_precondition_check(_To, _From)> {};
#else // ^^^ Use intrinsic / intrinsic not supported vvv
template <class _To, class _From>
using _Is_assignable_no_precondition_check = is_assignable<_To, _From>;
#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__)

template <class _Ty>
struct is_copy_assignable
: bool_constant<__is_assignable(add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {
Expand Down
112 changes: 112 additions & 0 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,15 @@ struct pair { // store a pair of values
pair(const pair&) = default;
pair(pair&&) = default;

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1&>, is_constructible<_Ty2, _Other2&>>, int> = 0>
constexpr explicit(!conjunction_v<is_convertible<_Other1&, _Ty1>, is_convertible<_Other2&, _Ty2>>)
pair(pair<_Other1, _Other2>& _Right) noexcept(
is_nothrow_constructible_v<_Ty1, _Other1&>&& is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened
: first(_Right.first), second(_Right.second) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, const _Other1&>, is_constructible<_Ty2, const _Other2&>>,
Expand Down Expand Up @@ -278,6 +287,16 @@ struct pair { // store a pair of values
: first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, const _Other1>, is_constructible<_Ty2, const _Other2>>, int> =
0>
constexpr explicit(!conjunction_v<is_convertible<const _Other1, _Ty1>, is_convertible<const _Other2, _Ty2>>)
pair(const pair<_Other1, _Other2>&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, const _Other1>&&
is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened
: first(_STD forward<const _Other1>(_Right.first)), second(_STD forward<const _Other2>(_Right.second)) {}
#endif // _HAS_CXX23

template <class _Tuple1, class _Tuple2, size_t... _Indexes1, size_t... _Indexes2>
constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>)
: first(_Tuple_get<_Indexes1>(_STD move(_Val1))...), second(_Tuple_get<_Indexes2>(_STD move(_Val2))...) {}
Expand All @@ -299,6 +318,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_copy_assignable_no_precondition_check<const typename _Myself::first_type>,
_Is_copy_assignable_no_precondition_check<const typename _Myself::second_type>>,
int> = 0>
constexpr const pair& operator=(_Identity_t<const _Myself&> _Right) const
noexcept(conjunction_v<is_nothrow_copy_assignable<const _Ty1>,
is_nothrow_copy_assignable<const _Ty2>>) /* strengthened */ {
first = _Right.first;
second = _Right.second;
return *this;
}
#endif // _HAS_CXX23

template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_move_assignable_no_precondition_check<typename _Myself::first_type>,
_Is_move_assignable_no_precondition_check<typename _Myself::second_type>>,
Expand All @@ -310,6 +343,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_assignable_no_precondition_check<const typename _Myself::first_type&, _Ty1>,
_Is_assignable_no_precondition_check<const typename _Myself::second_type&, _Ty2>>,
int> = 0>
constexpr const pair& operator=(_Identity_t<_Myself&&> _Right) const
noexcept(conjunction_v<is_nothrow_assignable<const _Ty1&, _Ty1>,
is_nothrow_assignable<const _Ty2&, _Ty2>>) /* strengthened */ {
first = _STD forward<_Ty1>(_Right.first);
second = _STD forward<_Ty2>(_Right.second);
return *this;
}
#endif // _HAS_CXX23

template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<_Ty1&, const _Other1&>,
is_assignable<_Ty2&, const _Other2&>>,
Expand All @@ -322,6 +369,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>,
is_assignable<const _Ty1&, const _Other1&>, is_assignable<const _Ty2&, const _Other2&>>,
int> = 0>
constexpr const pair& operator=(const pair<_Other1, _Other2>& _Right) const
noexcept(is_nothrow_assignable_v<const _Ty1&, const _Other1&>&&
is_nothrow_assignable_v<const _Ty2&, const _Other2&>) /* strengthened */ {
first = _Right.first;
second = _Right.second;
return *this;
}
#endif // _HAS_CXX23

template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<_Ty1&, _Other1>,
is_assignable<_Ty2&, _Other2>>,
Expand All @@ -333,6 +394,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<const _Ty1&, _Other1>,
is_assignable<const _Ty2&, _Other2>>,
int> = 0>
constexpr const pair& operator=(pair<_Other1, _Other2>&& _Right) const
noexcept(is_nothrow_assignable_v<const _Ty1&, _Other1>&&
is_nothrow_assignable_v<const _Ty2&, _Other2>) /* strengthened */ {
first = _STD forward<_Other1>(_Right.first);
second = _STD forward<_Other2>(_Right.second);
return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void swap(pair& _Right) noexcept(
_Is_nothrow_swappable<_Ty1>::value&& _Is_nothrow_swappable<_Ty2>::value) {
if (this != _STD addressof(_Right)) {
Expand All @@ -341,6 +416,16 @@ struct pair { // store a pair of values
}
}

#if _HAS_CXX23
constexpr void swap(const pair& _Right) const
noexcept(is_nothrow_swappable_v<const _Ty1>&& is_nothrow_swappable_v<const _Ty2>) {
if (this != _STD addressof(_Right)) {
_Swap_adl(first, _Right.first);
_Swap_adl(second, _Right.second);
}
}
#endif // _HAS_CXX23

_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
};
Expand All @@ -355,6 +440,14 @@ _CONSTEXPR20 void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexce
_Left.swap(_Right);
}

#if _HAS_CXX23
template <class _Ty1, class _Ty2, enable_if_t<is_swappable_v<const _Ty1> && is_swappable_v<const _Ty2>, int> = 0>
constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
_Left.swap(_Right);
}
#endif // _HAS_CXX23

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
return _Left.first == _Right.first && _Left.second == _Right.second;
Expand Down Expand Up @@ -398,6 +491,25 @@ _NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^

#ifdef __cpp_lib_concepts
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2, template <class> class _TQual,
template <class> class _UQual>
requires requires {
typename pair<common_reference_t<_TQual<_Ty1>, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>;
}
struct basic_common_reference<pair<_Ty1, _Ty2>, pair<_Uty1, _Uty2>, _TQual, _UQual> {
using type = pair<common_reference_t<_TQual<_Ty1>, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>;
};

template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
requires requires {
typename pair<common_type_t<_Ty1, _Uty1>, common_type_t<_Ty2, _Uty2>>;
}
struct common_type<pair<_Ty1, _Ty2>, pair<_Uty1, _Uty2>> {
using type = pair<common_type_t<_Ty1, _Uty1>, common_type_t<_Ty2, _Uty2>>;
};
#endif // __cpp_lib_concepts

template <class _Ty>
struct _Unrefwrap_helper { // leave unchanged if not a reference_wrapper
using type = _Ty;
Expand Down
12 changes: 12 additions & 0 deletions stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,18 @@ public:
return *this;
}

#if _HAS_CXX23
constexpr const _Vb_reference& operator=(bool _Val) const noexcept {
if (_Val) {
*const_cast<_Vbase*>(_Getptr()) |= _Mask();
} else {
*const_cast<_Vbase*>(_Getptr()) &= ~_Mask();
}

return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void flip() noexcept {
*const_cast<_Vbase*>(_Getptr()) ^= _Mask();
}
Expand Down
36 changes: 36 additions & 0 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -2119,12 +2119,23 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al) no
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty1&& _Val1, _Uty2&& _Val2) noexcept;

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>& _Pair) noexcept;
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept;

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>&& _Pair) noexcept;

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept;
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty,
enable_if_t<_Is_specialization_v<_Ty, pair> && !_Is_deducible_as_pair<_Uty&>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept;
Expand Down Expand Up @@ -2165,6 +2176,18 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _U
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD forward<_Uty2>(_Val2)));
}

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>& _Pair) noexcept {
// equivalent to
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
// _STD forward_as_tuple(_Pair.first), _STD forward_as_tuple(_Pair.second));
return _STD make_tuple(piecewise_construct,
_STD uses_allocator_construction_args<typename _Ty::first_type>(_Al, _Pair.first),
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _Pair.second));
}
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept {
Expand All @@ -2186,6 +2209,19 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pa
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD get<1>(_STD move(_Pair))));
}

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept {
// equivalent to
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
// _STD forward_as_tuple(_STD get<0>(_STD move(_Pair)), _STD forward_as_tuple(_STD get<1>(_STD move(_Pair)));
return _STD make_tuple(piecewise_construct,
_STD uses_allocator_construction_args<typename _Ty::first_type>(_Al, _STD get<0>(_STD move(_Pair))),
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD get<1>(_STD move(_Pair))));
}
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty,
enable_if_t<_Is_specialization_v<_Ty, pair> && !_Is_deducible_as_pair<_Uty&>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept {
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
// P2186R2 Removing Garbage Collection Support
// P2273R3 constexpr unique_ptr
// P2321R2 zip
// (changes to pair, tuple, and vector<bool>::reference only)
// P2443R1 views::chunk_by

// Parallel Algorithms Notes
Expand Down
5 changes: 3 additions & 2 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ std/utilities/format/format.functions/vformat_to.pass.cpp FAIL
std/utilities/format/format.functions/vformat.locale.pass.cpp FAIL
std/utilities/format/format.functions/vformat.pass.cpp FAIL

# libc++ doesn't implement P2321R2's changes to vector<bool>::reference
std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp FAIL


# *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX ***
# Tracked by VSO-593630 "<filesystem> Enable libcxx filesystem tests"
Expand Down Expand Up @@ -230,8 +233,6 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_literal_type.deprecated.fail.cp
# P2321R2 zip
std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/utility.version.pass.cpp FAIL
std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp FAIL
std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp FAIL

# P1328R1 constexpr type_info::operator==()
std/language.support/support.limits/support.limits.general/typeinfo.version.pass.cpp FAIL
Expand Down
5 changes: 3 additions & 2 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ utilities\format\format.functions\vformat_to.pass.cpp
utilities\format\format.functions\vformat.locale.pass.cpp
utilities\format\format.functions\vformat.pass.cpp

# libc++ doesn't implement P2321R2's changes to vector<bool>::reference
containers\sequences\vector.bool\iterator_concept_conformance.compile.pass.cpp


# *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX ***
# Tracked by VSO-593630 "<filesystem> Enable libcxx filesystem tests"
Expand Down Expand Up @@ -230,8 +233,6 @@ utilities\meta\meta.unary\meta.unary.prop\is_literal_type.deprecated.fail.cpp
# P2321R2 zip
language.support\support.limits\support.limits.general\tuple.version.pass.cpp
language.support\support.limits\support.limits.general\utility.version.pass.cpp
utilities\meta\meta.trans\meta.trans.other\common_reference.compile.pass.cpp
utilities\meta\meta.trans\meta.trans.other\common_type.pass.cpp

# P1328R1 constexpr type_info::operator==()
language.support\support.limits\support.limits.general\typeinfo.version.pass.cpp
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ tests\P2136R3_invoke_r
tests\P2162R2_std_visit_for_derived_classes_from_variant
tests\P2231R1_complete_constexpr_optional_variant
tests\P2273R3_constexpr_unique_ptr
tests\P2321R2_proxy_reference
tests\P2401R0_conditional_noexcept_for_exchange
tests\P2415R2_owning_view
tests\P2443R1_views_chunk_by
Expand Down
6 changes: 6 additions & 0 deletions tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ namespace Meow {

constexpr Evil() noexcept : data(1701) {}

template <int = 0>
const Evil& operator=(const Evil&) const {
// provide an Evil operator= for std::tuple::swap
return *this;
}

int func() const {
return 1729;
}
Expand Down
Loading

0 comments on commit f8748eb

Please sign in to comment.