зеркало из https://github.com/microsoft/STL.git
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:
Родитель
0a618dfb93
Коммит
f8748eb6d9
258
stl/inc/tuple
258
stl/inc/tuple
|
@ -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>)> {
|
||||
|
|
112
stl/inc/utility
112
stl/inc/utility
|
@ -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());
|
||||
}
|
Загрузка…
Ссылка в новой задаче