From 71bb4b4e7a3f6f1939a3390b556897d8bb318148 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 8 Jul 2024 07:11:33 +0800 Subject: [PATCH 1/3] Use `requires` for `pair` and `tuple` since C++20 --- stl/inc/tuple | 83 ++++++++++++++++++++++++------------------------- stl/inc/utility | 41 +++++++++++------------- 2 files changed, 58 insertions(+), 66 deletions(-) diff --git a/stl/inc/tuple b/stl/inc/tuple index 79315abf567..5093b2308f6 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -351,9 +351,9 @@ public: tuple(tuple&&) = default; #if _HAS_CXX23 - template , - _STD _Tuple_convert_val&, _Other...>>, - int> = 0> + template + requires _Tuple_constructible_v + && _Tuple_convert_val&, _Other...>::value constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} @@ -375,15 +375,16 @@ public: : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} #if _HAS_CXX23 - template , - _STD _Tuple_convert_val, _Other...>>, - int> = 0> + template + requires _Tuple_constructible_v + && _Tuple_convert_val, _Other...>::value constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} - template , int> = 0> + template + requires _Tuple_constructible_v constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened @@ -403,8 +404,8 @@ public: : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} #if _HAS_CXX23 - template , int> = 0> + template + requires _Tuple_constructible_v constexpr explicit(_Tuple_conditional_explicit_v) tuple(const pair<_First, _Second>&& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened @@ -419,7 +420,7 @@ public: is_convertible(_STD declval<_Other>())), _Rest>...>>; #if defined(__clang__) || defined(__EDG__) // TRANSITION, LLVM-59827 and VSO-1900279 - template , int> = 0> + template <_Can_construct_from_tuple_like _Other> #else // ^^^ workaround / no workaround vvv template <_Different_from _Other> requires _Tuple_like<_Other> && (!_Is_subrange_v>) @@ -464,10 +465,9 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template , - _STD _Tuple_convert_val&, _Other...>>, - int> = 0> + template + requires _Tuple_constructible_v + && _Tuple_convert_val&, _Other...>::value constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} @@ -490,16 +490,15 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template , - _STD _Tuple_convert_val, _Other...>>, - int> = 0> + template + requires _Tuple_constructible_v + && _Tuple_convert_val, _Other...>::value constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} - template , int> = 0> + template + requires _Tuple_constructible_v constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} @@ -518,14 +517,14 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template , int> = 0> + template + requires _Tuple_constructible_v constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if defined(__clang__) || defined(__EDG__) // TRANSITION, LLVM-59827 (Clang), VSO-1900279 (EDG) - template , int> = 0> + template _Other> #else // ^^^ workaround / no workaround vvv template _Other> requires _Tuple_like<_Other> && (!_Is_subrange_v>) @@ -553,12 +552,11 @@ public: } #if _HAS_CXX23 - template , - _STD _Is_copy_assignable_no_precondition_check...>, - int> = 0> + template + requires conjunction_v<_STD _Is_copy_assignable_no_precondition_check, + _STD _Is_copy_assignable_no_precondition_check...> constexpr const tuple& operator=(_Identity_t _Right) const - noexcept(conjunction_v, + noexcept(conjunction_v, is_nothrow_copy_assignable...>) /* strengthened */ { _Myfirst._Val = _Right._Myfirst._Val; _Get_rest() = _Right._Get_rest(); @@ -578,12 +576,11 @@ public: } #if _HAS_CXX23 - template , - _STD _Is_assignable_no_precondition_check...>, - int> = 0> + template + requires conjunction_v<_STD _Is_assignable_no_precondition_check, + _STD _Is_assignable_no_precondition_check...> constexpr const tuple& operator=(_Identity_t<_Myself&&> _Right) const - noexcept(conjunction_v, + noexcept(conjunction_v, is_nothrow_assignable...>) /* strengthened */ { _Myfirst._Val = _STD forward<_This>(_Right._Myfirst._Val); _Get_rest() = _STD forward<_Mybase>(_Right._Get_rest()); @@ -602,9 +599,8 @@ public: } #if _HAS_CXX23 - template >>, - _STD _Tuple_assignable_val>, - int> = 0> + template + requires (!is_same_v>) && _Tuple_assignable_v constexpr const tuple& operator=(const tuple<_Other...>& _Right) const noexcept(_Tuple_nothrow_assignable_v) /* strengthened */ { _Myfirst._Val = _Right._Myfirst._Val; @@ -624,9 +620,8 @@ public: } #if _HAS_CXX23 - template >>, - _STD _Tuple_assignable_val>, - int> = 0> + template + requires (!is_same_v>) && _Tuple_assignable_v constexpr const tuple& operator=(tuple<_Other...>&& _Right) const noexcept(_Tuple_nothrow_assignable_v) /* strengthened */ { _Myfirst._Val = _STD forward::_This_type>(_Right._Myfirst._Val); @@ -645,8 +640,8 @@ public: } #if _HAS_CXX23 - template , int> = 0> + template + requires _Tuple_assignable_v constexpr const tuple& operator=(const pair<_First, _Second>& _Right) const noexcept(_Tuple_nothrow_assignable_v) /* strengthened */ { _Myfirst._Val = _Right.first; @@ -664,7 +659,8 @@ public: } #if _HAS_CXX23 - template , int> = 0> + template + requires _Tuple_assignable_v constexpr const tuple& operator=(pair<_First, _Second>&& _Right) const noexcept(_Tuple_nothrow_assignable_v) /* strengthened */ { _Myfirst._Val = _STD forward<_First>(_Right.first); @@ -896,7 +892,8 @@ _CONSTEXPR20 void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right) noexce } #if _HAS_CXX23 -_EXPORT_STD template ...>, int> = 0> +_EXPORT_STD template + requires conjunction_v...> constexpr void swap(const tuple<_Types...>& _Left, const tuple<_Types...>& _Right) noexcept( noexcept(_Left.swap(_Right))) { _Left.swap(_Right); diff --git a/stl/inc/utility b/stl/inc/utility index e45d3b9bd5b..e03074023af 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -261,8 +261,8 @@ struct pair { // store a pair of values pair(pair&&) = default; #if _HAS_CXX23 - template , is_constructible<_Ty2, _Other2&>>, int> = 0> + template + requires is_constructible_v<_Ty1, _Other1&> && is_constructible_v<_Ty2, _Other2&> constexpr explicit(!conjunction_v, is_convertible<_Other2&, _Ty2>>) pair(pair<_Other1, _Other2>& _Right) noexcept( is_nothrow_constructible_v<_Ty1, _Other1&> && is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened @@ -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 , is_constructible<_Ty2, const _Other2>>, int> = - 0> + template + requires is_constructible_v<_Ty1, const _Other1> && is_constructible_v<_Ty2, const _Other2> constexpr explicit(!conjunction_v, is_convertible>) pair(const pair<_Other1, _Other2>&& _Right) noexcept( is_nothrow_constructible_v<_Ty1, const _Other1> @@ -335,10 +334,9 @@ struct pair { // store a pair of values } #if _HAS_CXX23 - template , - _Is_copy_assignable_no_precondition_check>, - int> = 0> + template + requires _Is_copy_assignable_unchecked_v + && _Is_copy_assignable_unchecked_v constexpr const pair& operator=(_Identity_t _Right) const noexcept(conjunction_v, is_nothrow_copy_assignable>) /* strengthened */ { @@ -360,10 +358,9 @@ struct pair { // store a pair of values } #if _HAS_CXX23 - template , - _Is_assignable_no_precondition_check>, - int> = 0> + template + requires _Is_assignable_no_precondition_check::value + && _Is_assignable_no_precondition_check::value constexpr const pair& operator=(_Identity_t<_Myself&&> _Right) const noexcept(conjunction_v, is_nothrow_assignable>) /* strengthened */ { @@ -386,10 +383,9 @@ struct pair { // store a pair of values } #if _HAS_CXX23 - template >>, - is_assignable, is_assignable>, - int> = 0> + template + requires (!is_same_v>) + && is_assignable_v && is_assignable_v constexpr const pair& operator=(const pair<_Other1, _Other2>& _Right) const noexcept(is_nothrow_assignable_v && is_nothrow_assignable_v) /* strengthened */ { @@ -411,10 +407,9 @@ struct pair { // store a pair of values } #if _HAS_CXX23 - template >>, is_assignable, - is_assignable>, - int> = 0> + template + requires (!is_same_v>) + && is_assignable_v && is_assignable_v constexpr const pair& operator=(pair<_Other1, _Other2>&& _Right) const noexcept(is_nothrow_assignable_v && is_nothrow_assignable_v) /* strengthened */ { @@ -481,8 +476,8 @@ _CONSTEXPR20 void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexce } #if _HAS_CXX23 -_EXPORT_STD template && is_swappable_v, int> = 0> +_EXPORT_STD template + requires is_swappable::value && is_swappable::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); From cf79b173bd10ef1da771374682b78b75594ebf01 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 8 Jul 2024 07:12:07 +0800 Subject: [PATCH 2/3] Unconditionally use `is_swappable::value` for `expected` --- stl/inc/expected | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 28e74e7118f..aad81b7007e 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -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); } @@ -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>) { From 907a98efa17825a8d69c9f7c39ff32ea58b3d0cf Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 9 Jul 2024 01:47:09 +0800 Subject: [PATCH 3/3] Give up changes for `tuple` constructors due to LLVM-59827 --- stl/inc/tuple | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/stl/inc/tuple b/stl/inc/tuple index 5093b2308f6..0f79be7872e 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -351,9 +351,9 @@ public: tuple(tuple&&) = default; #if _HAS_CXX23 - template - requires _Tuple_constructible_v - && _Tuple_convert_val&, _Other...>::value + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(tuple<_Other...>& _Right) noexcept(_Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _Right) {} @@ -375,16 +375,15 @@ public: : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} #if _HAS_CXX23 - template - requires _Tuple_constructible_v - && _Tuple_convert_val, _Other...>::value + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(const tuple<_Other...>&& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} - template - requires _Tuple_constructible_v + template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(pair<_First, _Second>& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened @@ -404,8 +403,8 @@ public: : tuple(_Unpack_tuple_t{}, _STD move(_Right)) {} #if _HAS_CXX23 - template - requires _Tuple_constructible_v + template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(const pair<_First, _Second>&& _Right) noexcept( _Tuple_nothrow_constructible_v) // strengthened @@ -420,7 +419,7 @@ public: is_convertible(_STD declval<_Other>())), _Rest>...>>; #if defined(__clang__) || defined(__EDG__) // TRANSITION, LLVM-59827 and VSO-1900279 - template <_Can_construct_from_tuple_like _Other> + template , int> = 0> #else // ^^^ workaround / no workaround vvv template <_Different_from _Other> requires _Tuple_like<_Other> && (!_Is_subrange_v>) @@ -465,9 +464,10 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template - requires _Tuple_constructible_v - && _Tuple_convert_val&, _Other...>::value + template , + _STD _Tuple_convert_val&, _Other...>>, + int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, tuple<_Other...>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} @@ -490,15 +490,16 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template - requires _Tuple_constructible_v - && _Tuple_convert_val, _Other...>::value + template , + _STD _Tuple_convert_val, _Other...>>, + int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const tuple<_Other...>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} - template - requires _Tuple_constructible_v + template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, pair<_First, _Second>& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _Right) {} @@ -517,14 +518,14 @@ public: : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if _HAS_CXX23 - template - requires _Tuple_constructible_v + template , int> = 0> constexpr explicit(_Tuple_conditional_explicit_v) tuple(allocator_arg_t, const _Alloc& _Al, const pair<_First, _Second>&& _Right) : tuple(_Alloc_unpack_tuple_t{}, _Al, _STD move(_Right)) {} #if defined(__clang__) || defined(__EDG__) // TRANSITION, LLVM-59827 (Clang), VSO-1900279 (EDG) - template _Other> + template , int> = 0> #else // ^^^ workaround / no workaround vvv template _Other> requires _Tuple_like<_Other> && (!_Is_subrange_v>)