P2321R2 zip: Make `tuple`, `pair`, and `vector<bool>::reference` `indirectly_writable` (#2687)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
S. B. Tam 2022-05-05 17:20:20 +08:00 коммит произвёл GitHub
Родитель 0a618dfb93
Коммит f8748eb6d9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 745 добавлений и 44 удалений

Просмотреть файл

@ -91,6 +91,12 @@ template <class... _Dests, class... _Srcs>
_INLINE_VAR constexpr bool _Tuple_assignable_v0<true, tuple<_Dests...>, _Srcs...> =
conjunction_v<is_assignable<_Dests&, _Srcs>...>; // note _Dests& instead of _Dests
#if _HAS_CXX23
template <class... _Dests, class... _Srcs>
inline constexpr bool _Tuple_assignable_v0<true, const tuple<_Dests...>, _Srcs...> =
conjunction_v<is_assignable<const _Dests&, _Srcs>...>;
#endif // _HAS_CXX23
template <class _Dest, class... _Srcs>
_INLINE_VAR constexpr bool _Tuple_assignable_v =
_Tuple_assignable_v0<tuple_size_v<_Dest> == sizeof...(_Srcs), _Dest, _Srcs...>;
@ -105,27 +111,24 @@ template <class... _Dests, class... _Srcs>
_INLINE_VAR constexpr bool _Tuple_nothrow_assignable_v0<true, tuple<_Dests...>, _Srcs...> =
conjunction_v<is_nothrow_assignable<_Dests&, _Srcs>...>; // note _Dests& instead of _Dests
#if _HAS_CXX23
template <class... _Dests, class... _Srcs>
inline constexpr bool _Tuple_nothrow_assignable_v0<true, const tuple<_Dests...>, _Srcs...> =
conjunction_v<is_nothrow_assignable<const _Dests&, _Srcs>...>;
#endif // _HAS_CXX23
template <class _Dest, class... _Srcs>
_INLINE_VAR constexpr bool _Tuple_nothrow_assignable_v =
_Tuple_nothrow_assignable_v0<tuple_size_v<_Dest> == sizeof...(_Srcs), _Dest, _Srcs...>;
// Constrain tuple's copy converting constructor (LWG-2549)
template <class _Myself, class... _Other>
struct _Tuple_convert_copy_val : true_type {};
// Constrain tuple's converting constructors
template <class _Myself, class _OtherTuple, class... _Other>
struct _Tuple_convert_val : true_type {};
template <class _This, class _Uty>
struct _Tuple_convert_copy_val<tuple<_This>, _Uty>
: bool_constant<!disjunction_v<is_same<_This, _Uty>, is_constructible<_This, const tuple<_Uty>&>,
is_convertible<const tuple<_Uty>&, _This>>> {};
// Constrain tuple's move converting constructor (LWG-2549)
template <class _Myself, class... _Other>
struct _Tuple_convert_move_val : true_type {};
template <class _This, class _Uty>
struct _Tuple_convert_move_val<tuple<_This>, _Uty>
: bool_constant<!disjunction_v<is_same<_This, _Uty>, is_constructible<_This, tuple<_Uty>>,
is_convertible<tuple<_Uty>, _This>>> {};
template <class _This, class _OtherTuple, class _Uty>
struct _Tuple_convert_val<tuple<_This>, _OtherTuple, _Uty>
: bool_constant<!disjunction_v<is_same<_This, _Uty>, is_constructible<_This, _OtherTuple>,
is_convertible<_OtherTuple, _This>>> {};
// Constrain tuple's perfect forwarding constructor (LWG-3121)
template <class _Myself, class _This2, class... _Rest2>
@ -225,8 +228,16 @@ public:
constexpr tuple(_Tag, const _Alloc&) noexcept /* strengthened */ {}
constexpr tuple& operator=(const tuple&) = default;
#if _HAS_CXX23
constexpr const tuple& operator=(const tuple&) const noexcept /* strengthened */ {
return *this;
}
#endif // _HAS_CXX23
_CONSTEXPR20 void swap(tuple&) noexcept {}
#if _HAS_CXX23
constexpr void swap(const tuple&) const noexcept {}
#endif // _HAS_CXX23
constexpr bool _Equals(const tuple&) const noexcept {
return true;
@ -355,9 +366,18 @@ public:
tuple(const tuple&) = default;
tuple(tuple&&) = default;
#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v<tuple, _Other&...>) // strengthened
: tuple(_Unpack_tuple_t{}, _Right) {}
#endif // _HAS_CXX23
#if _HAS_CONDITIONAL_EXPLICIT
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
_STD _Tuple_convert_copy_val<tuple, _Other...>>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other&...>)
tuple(const tuple<_Other...>& _Right) noexcept(
@ -365,14 +385,14 @@ public:
: tuple(_Unpack_tuple_t{}, _Right) {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class... _Other, enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, const _Other&...>,
_Tuple_convert_copy_val<tuple, _Other...>>,
_Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr tuple(const tuple<_Other...>& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _Other&...>) // strengthened
: tuple(_Unpack_tuple_t{}, _Right) {}
template <class... _Other, enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, const _Other&...>,
_Tuple_convert_copy_val<tuple, _Other...>>,
_Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit tuple(const tuple<_Other...>& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _Other&...>) // strengthened
@ -381,27 +401,43 @@ public:
#if _HAS_CONDITIONAL_EXPLICIT
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other...>,
_STD _Tuple_convert_move_val<tuple, _Other...>>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other...>)
tuple(tuple<_Other...>&& _Right) noexcept(_Tuple_nothrow_constructible_v<tuple, _Other...>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class... _Other,
enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, _Other...>, _Tuple_convert_move_val<tuple, _Other...>>,
int> = 0>
template <class... _Other, enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, _Other...>,
_Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
constexpr tuple(tuple<_Other...>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, _Other...>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
template <class... _Other,
enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, _Other...>, _Tuple_convert_move_val<tuple, _Other...>>,
int> = 0>
template <class... _Other, enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, _Other...>,
_Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit tuple(tuple<_Other...>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, _Other...>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
tuple(const tuple<_Other...>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _Other...>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
template <class _First, class _Second, enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
tuple(pair<_First, _Second>& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, _First&, _Second&>) // strengthened
: tuple(_Unpack_tuple_t{}, _Right) {}
#endif // _HAS_CXX23
#if _HAS_CONDITIONAL_EXPLICIT
template <class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
@ -440,6 +476,15 @@ public:
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
#if _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
tuple(const pair<_First, _Second>&& _Right) noexcept(
_Tuple_nothrow_constructible_v<tuple, const _First, const _Second>) // strengthened
: tuple(_Unpack_tuple_t{}, _STD move(_Right)) {}
#endif // _HAS_CXX23
#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class _This2 = _This,
enable_if_t<conjunction_v<_STD is_default_constructible<_This2>, _STD is_default_constructible<_Rest>...>,
@ -516,25 +561,35 @@ public:
_CONSTEXPR20 tuple(allocator_arg_t, const _Alloc& _Al, tuple&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#if _HAS_CXX23
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other&...>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>&, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _Other&...>)
tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
#endif // _HAS_CXX23
#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other&...>,
_STD _Tuple_convert_copy_val<tuple, _Other...>>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
_CONSTEXPR20 explicit(_Tuple_conditional_explicit_v<tuple, const _Other&...>)
tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class _Alloc, class... _Other,
enable_if_t<
conjunction_v<_Tuple_implicit_val<tuple, const _Other&...>, _Tuple_convert_copy_val<tuple, _Other...>>,
enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, const _Other&...>,
_Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
_CONSTEXPR20 tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
template <class _Alloc, class... _Other,
enable_if_t<
conjunction_v<_Tuple_explicit_val<tuple, const _Other&...>, _Tuple_convert_copy_val<tuple, _Other...>>,
enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, const _Other&...>,
_Tuple_convert_val<tuple, const tuple<_Other...>&, _Other...>>,
int> = 0>
_CONSTEXPR20 explicit tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
@ -543,25 +598,43 @@ public:
#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, _Other...>,
_STD _Tuple_convert_move_val<tuple, _Other...>>,
_STD _Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
_CONSTEXPR20 explicit(_Tuple_conditional_explicit_v<tuple, _Other...>)
tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, _Other...>, _Tuple_convert_move_val<tuple, _Other...>>,
enable_if_t<conjunction_v<_Tuple_implicit_val<tuple, _Other...>,
_Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
_CONSTEXPR20 tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, _Other...>, _Tuple_convert_move_val<tuple, _Other...>>,
enable_if_t<conjunction_v<_Tuple_explicit_val<tuple, _Other...>,
_Tuple_convert_val<tuple, tuple<_Other...>, _Other...>>,
int> = 0>
_CONSTEXPR20 explicit tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
#if _HAS_CXX23
template <class _Alloc, class... _Other,
enable_if_t<conjunction_v<_STD _Tuple_constructible_val<tuple, const _Other...>,
_STD _Tuple_convert_val<tuple, const tuple<_Other...>, _Other...>>,
int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _Other...>)
tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, _First&, _Second&>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, _First&, _Second&>)
tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {}
#endif // _HAS_CXX23
#if _HAS_CONDITIONAL_EXPLICIT
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First&, const _Second&>, int> = 0>
@ -598,6 +671,14 @@ public:
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^
#if _HAS_CXX23
template <class _Alloc, class _First, class _Second,
enable_if_t<_Tuple_constructible_v<tuple, const _First, const _Second>, int> = 0>
constexpr explicit(_Tuple_conditional_explicit_v<tuple, const _First, const _Second>)
tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right)
: tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {}
#endif // _HAS_CXX23
tuple& operator=(const volatile tuple&) = delete;
template <class _Myself = tuple, class _This2 = _This,
@ -611,6 +692,20 @@ public:
return *this;
}
#if _HAS_CXX23
template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_copy_assignable_no_precondition_check<const _This2>,
_STD _Is_copy_assignable_no_precondition_check<const _Rest>...>,
int> = 0>
constexpr const tuple& operator=(_Identity_t<const _Myself&> _Right) const
noexcept(conjunction_v<is_nothrow_copy_assignable<const _This2>,
is_nothrow_copy_assignable<const _Rest>...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
_Get_rest() = _Right._Get_rest();
return *this;
}
#endif // _HAS_CXX23
template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_move_assignable_no_precondition_check<_This2>,
_STD _Is_move_assignable_no_precondition_check<_Rest>...>,
@ -622,6 +717,20 @@ public:
return *this;
}
#if _HAS_CXX23
template <class _Myself = tuple, class _This2 = _This,
enable_if_t<conjunction_v<_STD _Is_assignable_no_precondition_check<const _This2&, _This2>,
_STD _Is_assignable_no_precondition_check<const _Rest&, _Rest>...>,
int> = 0>
constexpr const tuple& operator=(_Identity_t<_Myself&&> _Right) const
noexcept(conjunction_v<is_nothrow_assignable<const _This2&, _This2>,
is_nothrow_assignable<const _Rest&, _Rest>...>) /* strengthened */ {
_Myfirst._Val = _STD forward<_This>(_Right._Myfirst._Val);
_Get_rest() = _STD forward<_Mybase>(_Right._Get_rest());
return *this;
}
#endif // _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<tuple, const _Other&...>>,
int> = 0>
@ -632,6 +741,18 @@ public:
return *this;
}
#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<const tuple, const _Other&...>>,
int> = 0>
constexpr const tuple& operator=(const tuple<_Other...>& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _Other&...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
_Get_rest() = _Right._Get_rest();
return *this;
}
#endif // _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<tuple, _Other...>>,
int> = 0>
@ -642,6 +763,18 @@ public:
return *this;
}
#if _HAS_CXX23
template <class... _Other, enable_if_t<conjunction_v<_STD negation<_STD is_same<tuple, _STD tuple<_Other...>>>,
_STD _Tuple_assignable_val<const tuple, _Other...>>,
int> = 0>
constexpr const tuple& operator=(tuple<_Other...>&& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, _Other...>) /* strengthened */ {
_Myfirst._Val = _STD forward<typename tuple<_Other...>::_This_type>(_Right._Myfirst._Val);
_Get_rest() = _STD forward<typename tuple<_Other...>::_Mybase>(_Right._Get_rest());
return *this;
}
#endif // _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_assignable_v<tuple, const _First&, const _Second&>, int> = 0>
_CONSTEXPR20 tuple& operator=(const pair<_First, _Second>& _Right) noexcept(
@ -651,6 +784,17 @@ public:
return *this;
}
#if _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_assignable_v<const tuple, const _First&, const _Second&>, int> = 0>
constexpr const tuple& operator=(const pair<_First, _Second>& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _First&, const _Second&>) /* strengthened */ {
_Myfirst._Val = _Right.first;
_Get_rest()._Myfirst._Val = _Right.second;
return *this;
}
#endif // _HAS_CXX23
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<tuple, _First, _Second>, int> = 0>
_CONSTEXPR20 tuple& operator=(pair<_First, _Second>&& _Right) noexcept(
_Tuple_nothrow_assignable_v<tuple, _First, _Second>) /* strengthened */ {
@ -659,12 +803,30 @@ public:
return *this;
}
#if _HAS_CXX23
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<const tuple, _First, _Second>, int> = 0>
constexpr const tuple& operator=(pair<_First, _Second>&& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, _First, _Second>) /* strengthened */ {
_Myfirst._Val = _STD forward<_First>(_Right.first);
_Get_rest()._Myfirst._Val = _STD forward<_Second>(_Right.second);
return *this;
}
#endif // _HAS_CXX23
_CONSTEXPR20 void swap(tuple& _Right) noexcept(
conjunction_v<_Is_nothrow_swappable<_This>, _Is_nothrow_swappable<_Rest>...>) {
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
_Mybase::swap(_Right._Get_rest());
}
#if _HAS_CXX23
constexpr void swap(const tuple& _Right) const
noexcept(conjunction_v<is_nothrow_swappable<const _This>, is_nothrow_swappable<const _Rest>...>) {
_Swap_adl(_Myfirst._Val, _Right._Myfirst._Val);
_Mybase::swap(_Right._Get_rest());
}
#endif // _HAS_CXX23
constexpr _Mybase& _Get_rest() noexcept { // get reference to rest of elements
return *this;
}
@ -786,11 +948,19 @@ _NODISCARD constexpr bool operator<=(const tuple<_Types1...>& _Left, const tuple
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
template <class... _Types, enable_if_t<conjunction_v<_STD _Is_swappable<_Types>...>, int> = 0>
template <class... _Types, enable_if_t<conjunction_v<_Is_swappable<_Types>...>, int> = 0>
_CONSTEXPR20 void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
return _Left.swap(_Right);
}
#if _HAS_CXX23
template <class... _Types, enable_if_t<conjunction_v<is_swappable<const _Types>...>, int> = 0>
constexpr void swap(const tuple<_Types...>& _Left, const tuple<_Types...>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
return _Left.swap(_Right);
}
#endif // _HAS_CXX23
template <class _Ty, class _Tuple>
struct _Tuple_element {}; // backstop _Tuple_element definition
@ -1007,6 +1177,24 @@ _NODISCARD constexpr _Ty make_from_tuple(_Tuple&& _Tpl) { // construct _Ty from
template <class... _Types, class _Alloc>
struct uses_allocator<tuple<_Types...>, _Alloc> : true_type {}; // true_type if container allocator enabled
#ifdef __cpp_lib_concepts
template <class... _TTypes, class... _UTypes, template <class> class _TQual, template <class> class _UQual>
requires requires {
typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
}
struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> {
using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
};
template <class... _TTypes, class... _UTypes>
requires requires {
typename tuple<common_type_t<_TTypes, _UTypes>...>;
}
struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
using type = tuple<common_type_t<_TTypes, _UTypes>...>;
};
#endif // __cpp_lib_concepts
#if _HAS_TR1_NAMESPACE
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
using _STD get;

Просмотреть файл

@ -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>)> {

Просмотреть файл

@ -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&>>,
@ -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))...) {}
@ -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>>,
@ -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&>>,
@ -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>>,
@ -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)) {
@ -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
};
@ -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;
@ -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;

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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;
@ -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 {
@ -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 {

Просмотреть файл

@ -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

Просмотреть файл

@ -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"
@ -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

Просмотреть файл

@ -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"
@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -74,9 +74,13 @@ constexpr bool test_P0591R4() {
using ConstAllocatorConstructArgs = tuple<const int&, const allocator<int>&>;
using MovedAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&, int&&>;
using MovedAllocatorConstructArgs = tuple<int&&, const allocator<int>&>;
using OnlyAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&>;
using OnlyAllocatorConstructArgs = tuple<const allocator<int>&>;
using DefaultConstructArgs = tuple<>;
#if _HAS_CXX23
using MovedConstAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&, const int&&>;
using MovedConstAllocatorConstructArgs = tuple<const int&&, const allocator<int>&>;
#endif // _HAS_CXX23
using OnlyAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&>;
using OnlyAllocatorConstructArgs = tuple<const allocator<int>&>;
using DefaultConstructArgs = tuple<>;
{ // non-pair overload
auto tuple1 = uses_allocator_construction_args<int>(alloc, i);
@ -121,12 +125,31 @@ constexpr bool test_P0591R4() {
static_assert(is_same_v<decltype(tuple9), tuple<piecewise_construct_t, AllocatorConstructArgs, tuple<int&>>>);
}
{ // pair(const pair&) overload
{ // pair(const pair&) overload before C++23; pair(pair&) overload since C++23
auto tuple10 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, p);
#if _HAS_CXX23
static_assert(
is_same_v<decltype(tuple10), tuple<piecewise_construct_t, tuple<int&>, AllocatorArgConstructArgs>>);
#else // _HAS_CXX23
static_assert(is_same_v<decltype(tuple10),
tuple<piecewise_construct_t, tuple<const int&>, ConstAllocatorArgConstructArgs>>);
#endif // _HAS_CXX23
auto tuple11 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, p);
#if _HAS_CXX23
static_assert(is_same_v<decltype(tuple11), tuple<piecewise_construct_t, AllocatorConstructArgs, tuple<int&>>>);
#else // _HAS_CXX23
static_assert(
is_same_v<decltype(tuple11), tuple<piecewise_construct_t, ConstAllocatorConstructArgs, tuple<const int&>>>);
#endif // _HAS_CXX23
}
{ // pair(const pair&) overload
auto tuple10 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, as_const(p));
static_assert(is_same_v<decltype(tuple10),
tuple<piecewise_construct_t, tuple<const int&>, ConstAllocatorArgConstructArgs>>);
auto tuple11 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, p);
auto tuple11 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, as_const(p));
static_assert(
is_same_v<decltype(tuple11), tuple<piecewise_construct_t, ConstAllocatorConstructArgs, tuple<const int&>>>);
}
@ -141,6 +164,18 @@ constexpr bool test_P0591R4() {
is_same_v<decltype(tuple13), tuple<piecewise_construct_t, MovedAllocatorConstructArgs, tuple<int&&>>>);
}
#if _HAS_CXX23
{ // pair(const pair&&) overload
auto tuple12 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, move(as_const(p)));
static_assert(is_same_v<decltype(tuple12),
tuple<piecewise_construct_t, tuple<const int&&>, MovedConstAllocatorArgConstructArgs>>);
auto tuple13 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, move(as_const(p)));
static_assert(is_same_v<decltype(tuple13),
tuple<piecewise_construct_t, MovedConstAllocatorConstructArgs, tuple<const int&&>>>);
}
#endif // _HAS_CXX23
{
auto obj1 = make_obj_using_allocator<AllocatorArgConstructible>(alloc, i);
static_assert(is_same_v<decltype(obj1), AllocatorArgConstructible>);

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_latest_matrix.lst

Просмотреть файл

@ -0,0 +1,295 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <cassert>
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
using namespace std;
enum class State {
none,
copy_construct,
copy_construct_from_const,
move_construct,
move_construct_from_const,
copy_assign,
copy_assign_to_const,
move_assign,
move_assign_to_const,
swap,
swap_const,
};
struct Meow {
Meow() = default;
constexpr Meow(Meow&) : state(State::copy_construct) {}
constexpr Meow(const Meow&) : state(State::copy_construct_from_const) {}
constexpr Meow(Meow&&) : state(State::move_construct) {}
constexpr Meow(const Meow&&) : state(State::move_construct_from_const) {}
constexpr Meow& operator=(Meow&) = delete;
constexpr const Meow& operator=(Meow&) const = delete;
constexpr Meow& operator=(const Meow&) {
state = State::copy_assign;
return *this;
}
constexpr const Meow& operator=(const Meow&) const {
state = State::copy_assign_to_const;
return *this;
}
constexpr Meow& operator=(Meow&&) {
state = State::move_assign;
return *this;
}
constexpr const Meow& operator=(Meow&&) const {
state = State::move_assign_to_const;
return *this;
}
constexpr Meow& operator=(const Meow&&) = delete;
constexpr const Meow& operator=(const Meow&&) const = delete;
friend constexpr void swap(Meow& left, Meow&) {
left.state = State::swap;
}
friend constexpr void swap(const Meow& left, const Meow&) {
left.state = State::swap_const;
}
mutable State state;
};
constexpr bool test() {
{ // Test pair and tuple
int val = 0;
pair<int&, Meow> pris{val, Meow{}};
// Test pair construction
pair<int&, Meow> pris2 = pris;
pair<int&, Meow> pris3 = as_const(pris);
pair<int&, Meow> pris4 = move(pris);
pair<int&, Meow> pris5 = move(as_const(pris));
pair<const int&, Meow> prcis1 = pris;
pair<const int&, Meow> prcis2 = as_const(pris);
pair<const int&, Meow> prcis3 = move(pris);
pair<const int&, Meow> prcis4 = move(as_const(pris));
assert(pris2.second.state == State::copy_construct);
assert(pris3.second.state == State::copy_construct_from_const);
assert(pris4.second.state == State::move_construct);
assert(pris5.second.state == State::move_construct_from_const);
assert(prcis1.second.state == State::copy_construct);
assert(prcis2.second.state == State::copy_construct_from_const);
assert(prcis3.second.state == State::move_construct);
assert(prcis4.second.state == State::move_construct_from_const);
// Test pair assignment from lvalue
pris2 = pris4;
as_const(pris3) = pris5;
pris4 = prcis1;
as_const(pris5) = prcis2;
assert(pris2.second.state == State::copy_assign);
assert(pris3.second.state == State::copy_assign_to_const);
assert(pris4.second.state == State::copy_assign);
assert(pris5.second.state == State::copy_assign_to_const);
// Test pair assignment from rvalue
pris2 = move(pris4);
as_const(pris3) = move(pris5);
pris4 = move(prcis1);
as_const(pris5) = move(prcis2);
assert(pris2.second.state == State::move_assign);
assert(pris3.second.state == State::move_assign_to_const);
assert(pris4.second.state == State::move_assign);
assert(pris5.second.state == State::move_assign_to_const);
// Test pair member swap
pris.swap(pris2);
as_const(pris2).swap(as_const(pris3));
assert(pris.second.state == State::swap);
assert(pris2.second.state == State::swap_const);
// Test pair non-member swap
swap(pris3, pris5);
swap(as_const(pris4), as_const(pris5));
assert(pris3.second.state == State::swap);
assert(pris4.second.state == State::swap_const);
static_assert(is_nothrow_swappable_v<pair<int&, int&>>);
static_assert(is_nothrow_swappable_v<const pair<int&, int&>>);
static_assert(!is_nothrow_swappable_v<pair<int&, Meow>>);
static_assert(!is_nothrow_swappable_v<const pair<int&, Meow>>);
#ifdef __cpp_lib_concepts
// Test basic_common_reference and common_type specializations for pair
static_assert(is_same_v<common_reference_t<pair<int&, Meow>, pair<const int&, Meow>>, pair<const int&, Meow>>);
static_assert(is_same_v<common_reference_t<const pair<int&, Meow>, pair<const int&, Meow>>,
pair<const int&, const Meow>>);
static_assert(is_same_v<common_type_t<pair<int&, Meow>, pair<const int&, Meow>>, pair<int, Meow>>);
#endif // __cpp_lib_concepts
tuple<int&, Meow> tris{val, Meow{}};
// Test tuple construction (from tuple or pair)
tuple<int&, Meow> tris2 = tris;
tuple<int&, Meow> tris3 = as_const(tris);
tuple<int&, Meow> tris4 = move(tris);
tuple<int&, Meow> tris5 = move(as_const(tris));
tuple<int&, Meow> tris6 = pris;
tuple<int&, Meow> tris7 = as_const(pris);
tuple<int&, Meow> tris8 = move(pris);
tuple<int&, Meow> tris9 = move(as_const(pris));
tuple<const int&, Meow> trcis1 = tris;
tuple<const int&, Meow> trcis2 = as_const(tris);
tuple<const int&, Meow> trcis3 = move(tris);
tuple<const int&, Meow> trcis4 = move(as_const(tris));
tuple<const int&, Meow> trcis5 = pris;
tuple<const int&, Meow> trcis6 = as_const(pris);
tuple<const int&, Meow> trcis7 = move(pris);
tuple<const int&, Meow> trcis8 = move(as_const(pris));
assert(get<1>(tris2).state == State::copy_construct);
assert(get<1>(tris3).state == State::copy_construct_from_const);
assert(get<1>(tris4).state == State::move_construct);
assert(get<1>(tris5).state == State::move_construct_from_const);
assert(get<1>(tris6).state == State::copy_construct);
assert(get<1>(tris7).state == State::copy_construct_from_const);
assert(get<1>(tris8).state == State::move_construct);
assert(get<1>(tris9).state == State::move_construct_from_const);
assert(get<1>(trcis1).state == State::copy_construct);
assert(get<1>(trcis2).state == State::copy_construct_from_const);
assert(get<1>(trcis3).state == State::move_construct);
assert(get<1>(trcis4).state == State::move_construct_from_const);
assert(get<1>(trcis5).state == State::copy_construct);
assert(get<1>(trcis6).state == State::copy_construct_from_const);
assert(get<1>(trcis7).state == State::move_construct);
assert(get<1>(trcis8).state == State::move_construct_from_const);
// Test tuple uses-allocator construction
tuple<int&, Meow> tris10{allocator_arg, allocator<int>{}, tris};
tuple<int&, Meow> tris11{allocator_arg, allocator<int>{}, as_const(tris)};
tuple<int&, Meow> tris12{allocator_arg, allocator<int>{}, move(tris)};
tuple<int&, Meow> tris13{allocator_arg, allocator<int>{}, move(as_const(tris))};
tuple<int&, Meow> tris14{allocator_arg, allocator<int>{}, pris};
tuple<int&, Meow> tris15{allocator_arg, allocator<int>{}, as_const(pris)};
tuple<int&, Meow> tris16{allocator_arg, allocator<int>{}, move(pris)};
tuple<int&, Meow> tris17{allocator_arg, allocator<int>{}, move(as_const(pris))};
tuple<const int&, Meow> trcis9{allocator_arg, allocator<int>{}, tris};
tuple<const int&, Meow> trcis10{allocator_arg, allocator<int>{}, as_const(tris)};
tuple<const int&, Meow> trcis11{allocator_arg, allocator<int>{}, move(tris)};
tuple<const int&, Meow> trcis12{allocator_arg, allocator<int>{}, move(as_const(tris))};
tuple<const int&, Meow> trcis13{allocator_arg, allocator<int>{}, pris};
tuple<const int&, Meow> trcis14{allocator_arg, allocator<int>{}, as_const(pris)};
tuple<const int&, Meow> trcis15{allocator_arg, allocator<int>{}, move(pris)};
tuple<const int&, Meow> trcis16{allocator_arg, allocator<int>{}, move(as_const(pris))};
assert(get<1>(tris10).state == State::copy_construct);
assert(get<1>(tris11).state == State::copy_construct_from_const);
assert(get<1>(tris12).state == State::move_construct);
assert(get<1>(tris13).state == State::move_construct_from_const);
assert(get<1>(tris14).state == State::copy_construct);
assert(get<1>(tris15).state == State::copy_construct_from_const);
assert(get<1>(tris16).state == State::move_construct);
assert(get<1>(tris17).state == State::move_construct_from_const);
assert(get<1>(trcis9).state == State::copy_construct);
assert(get<1>(trcis10).state == State::copy_construct_from_const);
assert(get<1>(trcis11).state == State::move_construct);
assert(get<1>(trcis12).state == State::move_construct_from_const);
assert(get<1>(trcis13).state == State::copy_construct);
assert(get<1>(trcis14).state == State::copy_construct_from_const);
assert(get<1>(trcis15).state == State::move_construct);
assert(get<1>(trcis16).state == State::move_construct_from_const);
// Test tuple assignment from tuple lvalue
tris2 = tris;
as_const(tris3) = tris;
tris4 = trcis1;
as_const(tris5) = trcis2;
assert(get<1>(tris2).state == State::copy_assign);
assert(get<1>(tris3).state == State::copy_assign_to_const);
assert(get<1>(tris4).state == State::copy_assign);
assert(get<1>(tris5).state == State::copy_assign_to_const);
// Test tuple assignment from tuple rvalue
tris2 = move(tris);
as_const(tris3) = move(tris);
tris4 = move(trcis1);
as_const(tris5) = move(trcis2);
assert(get<1>(tris2).state == State::move_assign);
assert(get<1>(tris3).state == State::move_assign_to_const);
assert(get<1>(tris4).state == State::move_assign);
assert(get<1>(tris5).state == State::move_assign_to_const);
// Test tuple assignment from pair
tris2 = pris;
as_const(tris3) = pris;
tris4 = move(pris);
as_const(tris5) = move(pris);
assert(get<1>(tris2).state == State::copy_assign);
assert(get<1>(tris3).state == State::copy_assign_to_const);
assert(get<1>(tris4).state == State::move_assign);
assert(get<1>(tris5).state == State::move_assign_to_const);
// Test tuple member swap
tris2.swap(tris);
as_const(tris3).swap(tris);
assert(get<1>(tris2).state == State::swap);
assert(get<1>(tris3).state == State::swap_const);
// Test tuple non-member swap
swap(tris4, tris);
swap(as_const(tris5), as_const(tris));
assert(get<1>(tris4).state == State::swap);
assert(get<1>(tris5).state == State::swap_const);
static_assert(is_nothrow_swappable_v<tuple<int&, int&>>);
static_assert(is_nothrow_swappable_v<const tuple<int&, int&>>);
static_assert(!is_nothrow_swappable_v<tuple<int&, Meow>>);
static_assert(!is_nothrow_swappable_v<const tuple<int&, Meow>>);
#ifdef __cpp_lib_concepts
// Test basic_common_reference and common_type specializations for tuple
static_assert(
is_same_v<common_reference_t<tuple<int&, Meow>, tuple<const int&, Meow>>, tuple<const int&, Meow>>);
static_assert(is_same_v<common_reference_t<const tuple<int&, Meow>, tuple<const int&, Meow>>,
tuple<const int&, const Meow>>);
static_assert(is_same_v<common_type_t<tuple<int&, Meow>, tuple<const int&, Meow>>, tuple<int, Meow>>);
#endif // __cpp_lib_concepts
}
{ // Test vector<bool>::reference
static_assert(is_assignable_v<const vector<bool>::reference, bool>);
#if defined(__EDG__) && _ITERATOR_DEBUG_LEVEL != 0 // TRANSITION, VSO-1274387, VSO-1273296
if (!is_constant_evaluated())
#endif // defined(__EDG__) && _ITERATOR_DEBUG_LEVEL != 0
{
vector<bool> vb{false};
const vector<bool>::reference r = vb[0];
r = true;
assert(vb.front());
}
}
return true;
}
int main() {
test();
static_assert(test());
}