Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use requires-clauses for pair and tuple since C++20 #4819

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions stl/inc/expected
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,7 @@ public:
}

friend constexpr void swap(unexpected& _Left, unexpected& _Right) noexcept(is_nothrow_swappable_v<_Err>)
#if defined(__clang__) || defined(__EDG__) // TRANSITION, /permissive
requires is_swappable_v<_Err>
#else // ^^^ no workaround / workaround vvv
requires is_swappable<_Err>::value
#endif // ^^^ workaround ^^^
requires is_swappable<_Err>::value // TRANSITION, /permissive needs ::value
{
_Left.swap(_Right);
}
Expand Down Expand Up @@ -612,11 +608,7 @@ public:
friend constexpr void swap(expected& _Lhs, expected& _Rhs) noexcept(
is_nothrow_move_constructible_v<_Ty> && is_nothrow_swappable_v<_Ty> && is_nothrow_move_constructible_v<_Err>
&& is_nothrow_swappable_v<_Err>)
#if defined(__clang__) || defined(__EDG__) // TRANSITION, /permissive
requires is_swappable_v<_Ty> && is_swappable_v<_Err>
#else // ^^^ no workaround / workaround vvv
requires is_swappable<_Ty>::value && is_swappable<_Err>::value
#endif // ^^^ workaround ^^^
requires is_swappable<_Ty>::value && is_swappable<_Err>::value // TRANSITION, /permissive needs ::value
&& is_move_constructible_v<_Ty> && is_move_constructible_v<_Err>
&& (is_nothrow_move_constructible_v<_Ty> || is_nothrow_move_constructible_v<_Err>)
{
Expand Down
38 changes: 18 additions & 20 deletions stl/inc/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -553,12 +553,11 @@ public:
}

#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>
template <class _Myself = tuple>
requires conjunction_v<_STD _Is_copy_assignable_no_precondition_check<const _This>,
_STD _Is_copy_assignable_no_precondition_check<const _Rest>...>
constexpr const tuple& operator=(_Identity_t<const _Myself&> _Right) const
noexcept(conjunction_v<is_nothrow_copy_assignable<const _This2>,
noexcept(conjunction_v<is_nothrow_copy_assignable<const _This>,
is_nothrow_copy_assignable<const _Rest>...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
_Get_rest() = _Right._Get_rest();
Expand All @@ -578,12 +577,11 @@ public:
}

#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>
template <class _Myself = tuple>
requires conjunction_v<_STD _Is_assignable_no_precondition_check<const _This&, _This>,
_STD _Is_assignable_no_precondition_check<const _Rest&, _Rest>...>
constexpr const tuple& operator=(_Identity_t<_Myself&&> _Right) const
noexcept(conjunction_v<is_nothrow_assignable<const _This2&, _This2>,
noexcept(conjunction_v<is_nothrow_assignable<const _This&, _This>,
is_nothrow_assignable<const _Rest&, _Rest>...>) /* strengthened */ {
_Myfirst._Val = _STD forward<_This>(_Right._Myfirst._Val);
_Get_rest() = _STD forward<_Mybase>(_Right._Get_rest());
Expand All @@ -602,9 +600,8 @@ public:
}

#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>
template <class... _Other>
requires (!is_same_v<tuple, _STD tuple<_Other...>>) && _Tuple_assignable_v<const tuple, const _Other&...>
constexpr const tuple& operator=(const tuple<_Other...>& _Right) const
noexcept(_Tuple_nothrow_assignable_v<const tuple, const _Other&...>) /* strengthened */ {
_Myfirst._Val = _Right._Myfirst._Val;
Expand All @@ -624,9 +621,8 @@ public:
}

#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>
template <class... _Other>
requires (!is_same_v<tuple, _STD tuple<_Other...>>) && _Tuple_assignable_v<const tuple, _Other...>
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);
Expand All @@ -645,8 +641,8 @@ public:
}

#if _HAS_CXX23
template <class _First, class _Second,
enable_if_t<_Tuple_assignable_v<const tuple, const _First&, const _Second&>, int> = 0>
template <class _First, class _Second>
requires _Tuple_assignable_v<const tuple, const _First&, const _Second&>
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;
Expand All @@ -664,7 +660,8 @@ public:
}

#if _HAS_CXX23
template <class _First, class _Second, enable_if_t<_Tuple_assignable_v<const tuple, _First, _Second>, int> = 0>
template <class _First, class _Second>
requires _Tuple_assignable_v<const tuple, _First, _Second>
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);
Expand Down Expand Up @@ -896,7 +893,8 @@ _CONSTEXPR20 void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right) noexce
}

#if _HAS_CXX23
_EXPORT_STD template <class... _Types, enable_if_t<conjunction_v<is_swappable<const _Types>...>, int> = 0>
_EXPORT_STD template <class... _Types>
requires conjunction_v<is_swappable<const _Types>...>
constexpr void swap(const tuple<_Types...>& _Left, const tuple<_Types...>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
_Left.swap(_Right);
Expand Down
41 changes: 18 additions & 23 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ struct pair { // store a pair of values
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>
template <class _Other1, class _Other2>
requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&>
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
Expand All @@ -286,9 +286,8 @@ struct pair { // store a pair of values
: first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {}

#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>
template <class _Other1, class _Other2>
requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2>
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>
Expand Down Expand Up @@ -335,10 +334,9 @@ struct pair { // store a pair of values
}

#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>
template <class _Myself = pair>
requires _Is_copy_assignable_unchecked_v<const typename _Myself::first_type>
&& _Is_copy_assignable_unchecked_v<const typename _Myself::second_type>
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 */ {
Expand All @@ -360,10 +358,9 @@ struct pair { // store a pair of values
}

#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>
template <class _Myself = pair>
requires _Is_assignable_no_precondition_check<const typename _Myself::first_type&, _Ty1>::value
&& _Is_assignable_no_precondition_check<const typename _Myself::second_type&, _Ty2>::value
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 */ {
Expand All @@ -386,10 +383,9 @@ struct pair { // store a pair of values
}

#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>
template <class _Other1, class _Other2>
requires (!is_same_v<pair, pair<_Other1, _Other2>>)
&& is_assignable_v<const _Ty1&, const _Other1&> && is_assignable_v<const _Ty2&, const _Other2&>
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 */ {
Expand All @@ -411,10 +407,9 @@ struct pair { // store a pair of values
}

#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>
template <class _Other1, class _Other2>
requires (!is_same_v<pair, pair<_Other1, _Other2>>)
&& is_assignable_v<const _Ty1&, _Other1> && is_assignable_v<const _Ty2&, _Other2>
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 */ {
Expand Down Expand Up @@ -481,8 +476,8 @@ _CONSTEXPR20 void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexce
}

#if _HAS_CXX23
_EXPORT_STD template <class _Ty1, class _Ty2,
enable_if_t<is_swappable_v<const _Ty1> && is_swappable_v<const _Ty2>, int> = 0>
_EXPORT_STD template <class _Ty1, class _Ty2>
requires is_swappable<const _Ty1>::value && is_swappable<const _Ty2>::value // TRANSITION, /permissive needs ::value
constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
_Left.swap(_Right);
Expand Down