Skip to content

Commit

Permalink
Use requires-clauses for pair and tuple since C++20 (microsoft#…
Browse files Browse the repository at this point in the history
  • Loading branch information
frederick-vs-ja authored Jul 11, 2024
1 parent 0586819 commit ecbc1ef
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 53 deletions.
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

0 comments on commit ecbc1ef

Please sign in to comment.