From 23344e2643d87b3cf0783b9f03e419d4f0d04512 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 21 May 2024 06:50:10 +0800 Subject: [PATCH] Use `requires`-clauses and concepts for miscellaneous C++20/23 components (#4637) --- stl/inc/algorithm | 6 +- stl/inc/bit | 38 +++++++------ stl/inc/chrono | 34 ++++------- stl/inc/cmath | 4 +- stl/inc/compare | 3 +- stl/inc/functional | 21 ++++--- stl/inc/memory | 134 ++++++++++++++++++++++---------------------- stl/inc/numeric | 6 +- stl/inc/span | 3 +- stl/inc/sstream | 30 ++++++---- stl/inc/stop_token | 6 +- stl/inc/thread | 3 +- stl/inc/type_traits | 65 ++++++++++++--------- stl/inc/xmemory | 59 +++++++++---------- stl/inc/xutility | 20 +++---- 15 files changed, 227 insertions(+), 205 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index f55995e14..7f37e1cdc 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5799,7 +5799,8 @@ constexpr _FwdIt shift_left( return _First; } -_EXPORT_STD template = 0> +_EXPORT_STD template + requires requires { typename _Enable_if_execution_policy_t<_ExPo>; } _FwdIt shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) noexcept /* terminates */ { // shift [_First, _Last) left by _Pos_to_shift positions @@ -5883,7 +5884,8 @@ constexpr _FwdIt shift_right( } } -_EXPORT_STD template = 0> +_EXPORT_STD template + requires requires { typename _Enable_if_execution_policy_t<_ExPo>; } _FwdIt shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, typename iterator_traits<_FwdIt>::difference_type _Pos_to_shift) noexcept /* terminates */ { // shift [_First, _Last) right by _Pos_to_shift positions diff --git a/stl/inc/bit b/stl/inc/bit index a253dc1a5..9a73c6163 100644 --- a/stl/inc/bit +++ b/stl/inc/bit @@ -26,10 +26,8 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN -_EXPORT_STD template , is_trivially_copyable<_To>, - is_trivially_copyable<_From>>, - int> = 0> +_EXPORT_STD template + requires (sizeof(_To) == sizeof(_From)) && is_trivially_copyable_v<_To> && is_trivially_copyable_v<_From> _NODISCARD constexpr _To bit_cast(const _From& _Val) noexcept { return __builtin_bit_cast(_To, _Val); } @@ -61,7 +59,8 @@ _NODISCARD constexpr unsigned long long _Byteswap_uint64(const unsigned long lon } } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template + requires is_integral_v<_Ty> _NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { return _Val; @@ -77,17 +76,20 @@ _NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept { } #endif // _HAS_CXX23 -_EXPORT_STD template , int> = 0> +template +concept _Standard_unsigned_integral = _Is_standard_unsigned_integer<_Ty>; + +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int countl_zero(_Ty _Val) noexcept; -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept { return _Val != 0 && (_Val & (_Val - 1)) == 0; } inline void _Precondition_violation_in_bit_ceil() noexcept {} -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr _Ty bit_ceil(const _Ty _Val) noexcept /* strengthened */ { if (_Val <= 1u) { return _Ty{1}; @@ -115,7 +117,7 @@ _NODISCARD constexpr _Ty bit_ceil(const _Ty _Val) noexcept /* strengthened */ { return static_cast<_Ty>(_Ty{1} << _Num); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr _Ty bit_floor(const _Ty _Val) noexcept { if (_Val == 0) { return 0; @@ -124,15 +126,15 @@ _NODISCARD constexpr _Ty bit_floor(const _Ty _Val) noexcept { return static_cast<_Ty>(_Ty{1} << (_Unsigned_integer_digits<_Ty> - 1 - _STD countl_zero(_Val))); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int bit_width(const _Ty _Val) noexcept { return _Unsigned_integer_digits<_Ty> - _STD countl_zero(_Val); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr _Ty rotr(_Ty _Val, int _Rotation) noexcept; -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept { constexpr auto _Digits = _Unsigned_integer_digits<_Ty>; @@ -160,7 +162,7 @@ _NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept { } } -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr _Ty rotr(const _Ty _Val, const int _Rotation) noexcept { constexpr auto _Digits = _Unsigned_integer_digits<_Ty>; @@ -188,7 +190,7 @@ _NODISCARD constexpr _Ty rotr(const _Ty _Val, const int _Rotation) noexcept { } } -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept { #if _HAS_COUNTL_ZERO_INTRINSICS #if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) @@ -205,22 +207,22 @@ _NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept { return _Countl_zero_fallback(_Val); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int countl_one(const _Ty _Val) noexcept { return _STD countl_zero(static_cast<_Ty>(~_Val)); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int countr_zero(const _Ty _Val) noexcept { return _Countr_zero(_Val); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int countr_one(const _Ty _Val) noexcept { return _Countr_zero(static_cast<_Ty>(~_Val)); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr int popcount(const _Ty _Val) noexcept { return _Popcount(_Val); } diff --git a/stl/inc/chrono b/stl/inc/chrono index 5052abd45..8b3a2cbd2 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -2881,9 +2881,8 @@ namespace chrono { template struct clock_time_conversion { - template &>()))>> + template + requires requires(const time_point<_SourceClock, _Duration>& _Time) { _SourceClock::to_sys(_Time); } _NODISCARD auto operator()(const time_point<_SourceClock, _Duration>& _Time) const noexcept(noexcept(_SourceClock::to_sys(_Time))) /* strengthened */ { static_assert(_Is_time_point_for_clock, @@ -2895,8 +2894,8 @@ namespace chrono { template struct clock_time_conversion<_DestClock, system_clock> { - template &>()))>> + template + requires requires(const sys_time<_Duration>& _Time) { _DestClock::from_sys(_Time); } _NODISCARD auto operator()(const sys_time<_Duration>& _Time) const noexcept(noexcept(_DestClock::from_sys(_Time))) /* strengthened */ { static_assert(_Is_time_point_for_clock, @@ -2910,9 +2909,8 @@ namespace chrono { template struct clock_time_conversion { - template &>()))>> + template + requires requires(const time_point<_SourceClock, _Duration>& _Time) { _SourceClock::to_utc(_Time); } _NODISCARD auto operator()(const time_point<_SourceClock, _Duration>& _Time) const noexcept(noexcept(_SourceClock::to_utc(_Time))) /* strengthened */ { static_assert(_Is_time_point_for_clock, @@ -2924,8 +2922,8 @@ namespace chrono { template struct clock_time_conversion<_DestClock, utc_clock> { - template &>()))>> + template + requires requires(const utc_time<_Duration>& _Time) { _DestClock::from_utc(_Time); } _NODISCARD auto operator()(const utc_time<_Duration>& _Time) const noexcept(noexcept(_DestClock::from_utc(_Time))) /* strengthened */ { static_assert(_Is_time_point_for_clock, @@ -2948,19 +2946,11 @@ namespace chrono { _None, }; - template - constexpr bool _Has_two_step_conversion = false; - template - constexpr bool - _Has_two_step_conversion<_Conv1, _Conv2, _Tp, void_t())))>> = true; - - template - constexpr bool _Has_three_step_conversion = false; + constexpr bool _Has_two_step_conversion = requires { _Conv1{}(_Conv2{}(_STD declval<_Tp>())); }; template - constexpr bool _Has_three_step_conversion<_Conv1, _Conv2, _Conv3, _Tp, - void_t()))))>> = true; + constexpr bool _Has_three_step_conversion = requires { _Conv1{}(_Conv2{}(_Conv3{}(_STD declval<_Tp>()))); }; template _NODISCARD consteval _Clock_cast_strategy _Choose_clock_cast() noexcept { @@ -3008,8 +2998,8 @@ namespace chrono { template constexpr auto _Clock_cast_choice = _Choose_clock_cast<_DestClock, _SourceClock, _Duration>(); - _EXPORT_STD template != _Clock_cast_strategy::_None, int> = 0> + _EXPORT_STD template + requires (_Clock_cast_choice<_DestClock, _SourceClock, _Duration> != _Clock_cast_strategy::_None) _NODISCARD auto clock_cast(const time_point<_SourceClock, _Duration>& _Time) { constexpr auto _Strat = _Clock_cast_choice<_DestClock, _SourceClock, _Duration>; diff --git a/stl/inc/cmath b/stl/inc/cmath index b979948e8..de7be7abc 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -1617,8 +1617,8 @@ _EXPORT_STD _NODISCARD constexpr inline long double lerp( return _Common_lerp(_ArgA, _ArgB, _ArgT); } -_EXPORT_STD template && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3>, int> = 0> +_EXPORT_STD template + requires is_arithmetic_v<_Ty1> && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3> _NODISCARD constexpr auto lerp(const _Ty1 _ArgA, const _Ty2 _ArgB, const _Ty3 _ArgT) noexcept { using _Tgt = conditional_t<_Is_any_of_v, long double, double>; return _Common_lerp(static_cast<_Tgt>(_ArgA), static_cast<_Tgt>(_ArgB), static_cast<_Tgt>(_ArgT)); diff --git a/stl/inc/compare b/stl/inc/compare index 2829fa5b8..38246ebb6 100644 --- a/stl/inc/compare +++ b/stl/inc/compare @@ -24,7 +24,8 @@ _STD_BEGIN void _Literal_zero_is_expected(); struct _Literal_zero { - template , int> = 0> + template + requires is_same_v<_Ty, int> consteval _Literal_zero(_Ty _Zero) noexcept { // Can't use _STL_VERIFY because this is a core header if (_Zero != 0) { diff --git a/stl/inc/functional b/stl/inc/functional index 4e9f6792e..5150939b5 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1866,7 +1866,8 @@ public: move_only_function(move_only_function&&) noexcept = default; - template , int> = 0> + template + requires _Enable_one_arg_constructor<_Fn> move_only_function(_Fn&& _Callable) { using _Vt = decay_t<_Fn>; static_assert(is_constructible_v<_Vt, _Fn>, "_Vt should be constructible from _Fn. " @@ -1883,7 +1884,8 @@ public: this->template _Construct_with_fn<_Vt, _VtInvQuals>(_STD forward<_Fn>(_Callable)); } - template , int> = 0> + template + requires _Enable_in_place_constructor<_Fn, _CTypes...> explicit move_only_function(in_place_type_t<_Fn>, _CTypes&&... _Args) { using _Vt = decay_t<_Fn>; static_assert(is_same_v<_Vt, _Fn>, "_Vt should be the same type as _Fn. (N4950 [func.wrap.move.ctor]/12)"); @@ -1892,8 +1894,8 @@ public: this->template _Construct_with_fn<_Vt, _VtInvQuals>(_STD forward<_CTypes>(_Args)...); } - template , int> = 0> + template + requires _Enable_in_place_list_constructor<_Fn, _Ux, _CTypes...> explicit move_only_function(in_place_type_t<_Fn>, initializer_list<_Ux> _Li, _CTypes&&... _Args) { using _Vt = decay_t<_Fn>; static_assert(is_same_v<_Vt, _Fn>, "_Vt should be the same type as _Fn. (N4950 [func.wrap.move.ctor]/18)"); @@ -1923,7 +1925,8 @@ public: return *this; } - template , int> = 0> + template + requires is_constructible_v move_only_function& operator=(_Fn&& _Callable) { this->_Move_assign(move_only_function{_STD forward<_Fn>(_Callable)}); return *this; @@ -2243,8 +2246,8 @@ private: _STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...)); public: - template , _Front_binder>, int> = 0> + template + requires (sizeof...(_TypesInit) != 0 || !is_same_v, _Front_binder>) constexpr explicit _Front_binder(_FxInit&& _Func, _TypesInit&&... _Args) : _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {} @@ -2336,8 +2339,8 @@ private: _STL_INTERNAL_STATIC_ASSERT((is_same_v<_Types, decay_t<_Types>> && ...)); public: - template , _Back_binder>, int> = 0> + template + requires (sizeof...(_TypesInit) != 0 || !is_same_v, _Back_binder>) constexpr explicit _Back_binder(_FxInit&& _Func, _TypesInit&&... _Args) : _Mypair(_One_then_variadic_args_t{}, _STD forward<_FxInit>(_Func), _STD forward<_TypesInit>(_Args)...) {} diff --git a/stl/inc/memory b/stl/inc/memory index b0f59f2fc..61cb64602 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1542,6 +1542,20 @@ struct _Temporary_owner_del { } }; +#if _HAS_CXX20 +template +concept _Not_builtin_array = !is_array_v<_Ty>; + +template +concept _Bounded_builtin_array = is_bounded_array_v<_Ty>; + +template +concept _Unbounded_builtin_array = is_unbounded_array_v<_Ty>; + +template +concept _Not_unbounded_builtin_array = !is_unbounded_array_v<_Ty>; +#endif // _HAS_CXX20 + _EXPORT_STD template class shared_ptr : public _Ptr_base<_Ty> { // class for reference counted resource management private: @@ -1794,31 +1808,29 @@ private: } #if _HAS_CXX20 - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared(_Types&&... _Args); + template <_Not_builtin_array _Ty0, class... _Types> + friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + template <_Not_builtin_array _Ty0, class _Alloc, class... _Types> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared(); + template <_Bounded_builtin_array _Ty0> + friend shared_ptr<_Ty0> make_shared(); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg); + template <_Bounded_builtin_array _Ty0, class _Alloc> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg); - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared(const remove_extent_t<_Ty0>& _Val); + template <_Bounded_builtin_array _Ty0> + friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( - const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); + template <_Bounded_builtin_array _Ty0, class _Alloc> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared_for_overwrite(); + template <_Not_unbounded_builtin_array _Ty0> + friend shared_ptr<_Ty0> make_shared_for_overwrite(); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared_for_overwrite( - const _Alloc& _Al_arg); + template <_Not_unbounded_builtin_array _Ty0, class _Alloc> + friend shared_ptr<_Ty0> allocate_shared_for_overwrite(const _Alloc& _Al_arg); template friend shared_ptr<_Ty0> _Make_shared_unbounded_array(size_t _Count, const _ArgTypes&... _Args); @@ -2885,14 +2897,12 @@ private: }; #endif // _HAS_CXX20 -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC #if _HAS_CXX20 - enable_if_t, shared_ptr<_Ty>> -#else - shared_ptr<_Ty> -#endif - make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object +_EXPORT_STD template <_Not_builtin_array _Ty, class... _Types> +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv +template +#endif // ^^^ !_HAS_CXX20 ^^^ +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx); @@ -2928,19 +2938,18 @@ _NODISCARD shared_ptr<_Ty> _Make_shared_unbounded_array(const size_t _Count, con return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { +_EXPORT_STD template <_Unbounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared(const size_t _Count) { return _STD _Make_shared_unbounded_array<_Ty>(_Count); } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared( - const size_t _Count, const remove_extent_t<_Ty>& _Val) { +_EXPORT_STD template <_Unbounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared(const size_t _Count, const remove_extent_t<_Ty>& _Val) { return _STD _Make_shared_unbounded_array<_Ty>(_Count, _Val); } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared() { +_EXPORT_STD template <_Bounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; @@ -2948,9 +2957,8 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared( - const remove_extent_t<_Ty>& _Val) { +_EXPORT_STD template <_Bounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared(const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; @@ -2958,8 +2966,8 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite() { +_EXPORT_STD template <_Not_unbounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared_for_overwrite() { shared_ptr<_Ty> _Ret; if constexpr (is_array_v<_Ty>) { // make a shared_ptr to a bounded array @@ -2973,21 +2981,19 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_T return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite( - const size_t _Count) { +_EXPORT_STD template <_Unbounded_builtin_array _Ty> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> make_shared_for_overwrite(const size_t _Count) { return _STD _Make_shared_unbounded_array<_Ty>(_Count, _For_overwrite_tag{}); } #endif // _HAS_CXX20 -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC #if _HAS_CXX20 - enable_if_t, shared_ptr<_Ty>> -#else - shared_ptr<_Ty> -#endif - allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object +_EXPORT_STD template <_Not_builtin_array _Ty, class _Alloc, class... _Types> +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv +template +#endif // ^^^ !_HAS_CXX20 ^^^ +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) { + // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether // allocator::construct sees T or const T when _Ty is const qualified) using _Refoa = _Ref_count_obj_alloc3, _Alloc>; @@ -3044,20 +3050,19 @@ _NODISCARD shared_ptr<_Ty> _Allocate_shared_unbounded_array( return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( - const _Alloc& _Al, const size_t _Count) { +_EXPORT_STD template <_Unbounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const size_t _Count) { return _STD _Allocate_shared_unbounded_array(_Al, _Count); } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( +_EXPORT_STD template <_Unbounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { return _STD _Allocate_shared_unbounded_array(_Al, _Count, _Val); } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al) { +_EXPORT_STD template <_Bounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared(const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -3071,9 +3076,8 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( - const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { +_EXPORT_STD template <_Bounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -3087,9 +3091,8 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite( - const _Alloc& _Al) { +_EXPORT_STD template <_Not_unbounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared_for_overwrite(const _Alloc& _Al) { shared_ptr<_Ty> _Ret; if constexpr (is_array_v<_Ty>) { // make a shared_ptr to a bounded array @@ -3116,9 +3119,8 @@ _NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_T return _Ret; } -_EXPORT_STD template -_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite( - const _Alloc& _Al, const size_t _Count) { +_EXPORT_STD template <_Unbounded_builtin_array _Ty, class _Alloc> +_NODISCARD_SMART_PTR_ALLOC shared_ptr<_Ty> allocate_shared_for_overwrite(const _Alloc& _Al, const size_t _Count) { return _STD _Allocate_shared_unbounded_array(_Al, _Count); } #endif // _HAS_CXX20 @@ -3605,20 +3607,20 @@ _EXPORT_STD template != 0 void make_unique(_Types&&...) = delete; #if _HAS_CXX20 -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Not_builtin_array _Ty> _NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite() { // make a unique_ptr with default initialization return unique_ptr<_Ty>(new _Ty); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Unbounded_builtin_array _Ty> _NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite(const size_t _Size) { // make a unique_ptr with default initialization using _Elem = remove_extent_t<_Ty>; return unique_ptr<_Ty>(new _Elem[_Size]); } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Bounded_builtin_array _Ty, class... _Types> void make_unique_for_overwrite(_Types&&...) = delete; #endif // _HAS_CXX20 diff --git a/stl/inc/numeric b/stl/inc/numeric index a0186094e..ba63786e5 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -657,7 +657,8 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n #endif // _HAS_CXX17 #if _HAS_CXX20 -_EXPORT_STD template && !is_same_v, bool>, int> = 0> +_EXPORT_STD template + requires is_arithmetic_v<_Ty> && (!is_same_v, bool>) _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept { if constexpr (is_floating_point_v<_Ty>) { if (_STD is_constant_evaluated()) { @@ -722,7 +723,8 @@ _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept { } } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template + requires is_object_v<_Ty> _NODISCARD constexpr _Ty* midpoint(_Ty* const _Val1, _Ty* const _Val2) noexcept /* strengthened */ { if (_Val1 > _Val2) { return _Val1 - ((_Val1 - _Val2) >> 1); // shift for codegen diff --git a/stl/inc/span b/stl/inc/span index fe1e98744..d18667c64 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -549,7 +549,8 @@ _NODISCARD auto as_bytes(span<_Ty, _Extent> _Sp) noexcept { return _ReturnType{reinterpret_cast(_Sp.data()), _Sp.size_bytes()}; } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template + requires (!is_const_v<_Ty>) _NODISCARD auto as_writable_bytes(span<_Ty, _Extent> _Sp) noexcept { using _ReturnType = span; return _ReturnType{reinterpret_cast(_Sp.data()), _Sp.size_bytes()}; diff --git a/stl/inc/sstream b/stl/inc/sstream index 2a0ae5136..4d44166fa 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -61,7 +61,8 @@ public: basic_stringbuf(const basic_string<_Elem, _Traits, _Alloc2>& _Str, const _Alloc& _Al_) : basic_stringbuf(_Str, ios_base::in | ios_base::out, _Al_) {} - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) explicit basic_stringbuf( const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode = ios_base::in | ios_base::out) : basic_stringbuf(_Str, _Mode, _Alloc{}) {} @@ -229,7 +230,8 @@ public: } #if _HAS_CXX20 - template ::value, int> = 0> + template + requires _Is_allocator<_Alloc2>::value _NODISCARD basic_string<_Elem, _Traits, _Alloc2> str(const _Alloc2& _Al) const { return basic_string<_Elem, _Traits, _Alloc2>{view(), _Al}; } @@ -260,7 +262,8 @@ public: return _Mystr_view{_View._Ptr, _View._Size}; } - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) void str(const basic_string<_Elem, _Traits, _Alloc2>& _Newstr) { _Tidy(); _Init(_Newstr.c_str(), _Newstr.size(), _Mystate); @@ -641,7 +644,8 @@ public: basic_istringstream(const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode, const _Alloc& _Al) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::in, _Al) {} - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) explicit basic_istringstream( const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode = ios_base::in) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::in) {} @@ -690,7 +694,8 @@ public: } #if _HAS_CXX20 - template ::value, int> = 0> + template + requires _Is_allocator<_Alloc2>::value _NODISCARD basic_string<_Elem, _Traits, _Alloc2> str(const _Alloc2& _Al) const { return _Stringbuffer.str(_Al); } @@ -703,7 +708,8 @@ public: return _Stringbuffer.view(); } - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) void str(const basic_string<_Elem, _Traits, _Alloc2>& _Newstr) { _Stringbuffer.str(_Newstr); } @@ -758,7 +764,8 @@ public: basic_ostringstream(const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode, const _Alloc& _Al) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::out, _Al) {} - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) explicit basic_ostringstream( const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode = ios_base::out) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::out) {} @@ -820,7 +827,8 @@ public: return _Stringbuffer.view(); } - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) void str(const basic_string<_Elem, _Traits, _Alloc2>& _Newstr) { _Stringbuffer.str(_Newstr); } @@ -881,7 +889,8 @@ public: basic_stringstream(const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode, const _Alloc& _Al) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode, _Al) {} - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) explicit basic_stringstream( const basic_string<_Elem, _Traits, _Alloc2>& _Str, ios_base::openmode _Mode = ios_base::in | ios_base::out) : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode) {} @@ -943,7 +952,8 @@ public: return _Stringbuffer.view(); } - template , int> = 0> + template + requires (!is_same_v<_Alloc2, _Alloc>) void str(const basic_string<_Elem, _Traits, _Alloc2>& _Newstr) { _Stringbuffer.str(_Newstr); } diff --git a/stl/inc/stop_token b/stl/inc/stop_token index cec4ddc59..5702d9021 100644 --- a/stl/inc/stop_token +++ b/stl/inc/stop_token @@ -357,14 +357,16 @@ class stop_callback : public _Stop_callback_base { public: using callback_type = _Callback; - template , int> = 0> + template + requires is_constructible_v<_Callback, _CbInitTy> explicit stop_callback(const stop_token& _Token, _CbInitTy&& _Cb_) noexcept( is_nothrow_constructible_v<_Callback, _CbInitTy>) : _Stop_callback_base{_Invoke_by_stop}, _Cb(_STD forward<_CbInitTy>(_Cb_)) { _Attach(_Token); } - template , int> = 0> + template + requires is_constructible_v<_Callback, _CbInitTy> explicit stop_callback(stop_token&& _Token, _CbInitTy&& _Cb_) noexcept( is_nothrow_constructible_v<_Callback, _CbInitTy>) : _Stop_callback_base{_Invoke_by_stop}, _Cb(_STD forward<_CbInitTy>(_Cb_)) { diff --git a/stl/inc/thread b/stl/inc/thread index d96369fd4..079f4b7af 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -350,7 +350,8 @@ public: jthread() noexcept : _Impl{}, _Ssource{nostopstate} {} - template , jthread>, int> = 0> + template + requires (!is_same_v, jthread>) _NODISCARD_CTOR_JTHREAD explicit jthread(_Fn&& _Fx, _Args&&... _Ax) { if constexpr (is_invocable_v, stop_token, decay_t<_Args>...>) { _Impl._Start(_STD forward<_Fn>(_Fx), _Ssource.get_token(), _STD forward<_Args>(_Ax)...); diff --git a/stl/inc/type_traits b/stl/inc/type_traits index cb7feb0e3..a38a56b9d 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1295,13 +1295,23 @@ template using _Conditional_type = decltype(false ? _STD declval<_Ty1>() : _STD declval<_Ty2>()); #if _HAS_CXX20 +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10648215 +template +#else // ^^^ no workaround / workaround vvv template -struct _Const_lvalue_cond_oper {}; +#endif // ^^^ workaround ^^^ +struct _Const_lvalue_cond_oper { +}; // N4950 [meta.trans.other]/3.3.4 (per the proposed resolution of LWG-3205): "Otherwise, if remove_cvref_t denotes // a type..." template +#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10648215 + requires requires { typename _Conditional_type; } +struct _Const_lvalue_cond_oper<_Ty1, _Ty2> { +#else // ^^^ no workaround / workaround vvv struct _Const_lvalue_cond_oper<_Ty1, _Ty2, void_t<_Conditional_type>> { +#endif // ^^^ workaround ^^^ using type = remove_cvref_t<_Conditional_type>; }; @@ -1419,12 +1429,13 @@ struct common_reference<_Ty> { // N4950 [meta.trans.other]/5.3.4: "if common_type_t is well-formed..." // N4950 [meta.trans.other]/5.3.5: "Otherwise, there shall be no member type." -template +template struct _Common_reference2C : common_type<_Ty1, _Ty2> {}; // N4950 [meta.trans.other]/5.3.3: "if COND_RES(T1, T2) is well-formed..." template -struct _Common_reference2C<_Ty1, _Ty2, void_t<_Cond_res<_Ty1, _Ty2>>> { + requires requires { typename _Cond_res<_Ty1, _Ty2>; } +struct _Common_reference2C<_Ty1, _Ty2> { using type = _Cond_res<_Ty1, _Ty2>; }; @@ -1433,39 +1444,43 @@ template using _Basic_specialization = basic_common_reference, remove_cvref_t<_Ty2>, _Add_qualifiers<_Ty1>::template _Apply, _Add_qualifiers<_Ty2>::template _Apply>::type; -template +template struct _Common_reference2B : _Common_reference2C<_Ty1, _Ty2> {}; template -struct _Common_reference2B<_Ty1, _Ty2, void_t<_Basic_specialization<_Ty1, _Ty2>>> { + requires requires { typename _Basic_specialization<_Ty1, _Ty2>; } +struct _Common_reference2B<_Ty1, _Ty2> { using type = _Basic_specialization<_Ty1, _Ty2>; }; // N4950 [meta.trans.other]/5.3.1: "Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed, and // is_convertible_v, add_pointer_t> && is_convertible_v, add_pointer_t> is // true, then the member typedef type denotes R." -template +template struct _Common_reference2A : _Common_reference2B<_Ty1, _Ty2> {}; -template &, _Copy_cv<_Ty2, _Ty1>&>, - enable_if_t, int> = 0> -using _LL_common_ref = _Result; +template + requires is_lvalue_reference_v<_Cond_res<_Copy_cv<_Ty1, _Ty2>&, _Copy_cv<_Ty2, _Ty1>&>> +using _LL_common_ref = _Cond_res<_Copy_cv<_Ty1, _Ty2>&, _Copy_cv<_Ty2, _Ty1>&>; -template +template struct _Common_reference2AX {}; template -struct _Common_reference2AX<_Ty1&, _Ty2&, void_t<_LL_common_ref<_Ty1, _Ty2>>> { + requires requires { typename _LL_common_ref<_Ty1, _Ty2>; } +struct _Common_reference2AX<_Ty1&, _Ty2&> { using type = _LL_common_ref<_Ty1, _Ty2>; // "both lvalues" case from N4950 [meta.trans.other]/2.5 }; template -struct _Common_reference2AX<_Ty1&&, _Ty2&, enable_if_t>>> { + requires is_convertible_v<_Ty1&&, _LL_common_ref> +struct _Common_reference2AX<_Ty1&&, _Ty2&> { using type = _LL_common_ref; // "rvalue and lvalue" case from N4950 [meta.trans.other]/2.7 }; template -struct _Common_reference2AX<_Ty1&, _Ty2&&, enable_if_t>>> { + requires is_convertible_v<_Ty2&&, _LL_common_ref> +struct _Common_reference2AX<_Ty1&, _Ty2&&> { using type = _LL_common_ref; // "lvalue and rvalue" case from N4950 [meta.trans.other]/2.8 }; @@ -1473,9 +1488,9 @@ template using _RR_common_ref = remove_reference_t<_LL_common_ref<_Ty1, _Ty2>>&&; template -struct _Common_reference2AX<_Ty1&&, _Ty2&&, - enable_if_t> - && is_convertible_v<_Ty2&&, _RR_common_ref<_Ty1, _Ty2>>>> { + requires is_convertible_v<_Ty1&&, _RR_common_ref<_Ty1, _Ty2>> + && is_convertible_v<_Ty2&&, _RR_common_ref<_Ty1, _Ty2>> +struct _Common_reference2AX<_Ty1&&, _Ty2&&> { using type = _RR_common_ref<_Ty1, _Ty2>; // "both rvalues" case from N4950 [meta.trans.other]/2.6 }; @@ -1483,9 +1498,9 @@ template using _Common_ref_2AX_t = _Common_reference2AX<_Ty1, _Ty2>::type; template -struct _Common_reference2A<_Ty1, _Ty2, - enable_if_t, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>> - && is_convertible_v, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>>>> { + requires is_convertible_v, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>> + && is_convertible_v, add_pointer_t<_Common_ref_2AX_t<_Ty1, _Ty2>>> +struct _Common_reference2A<_Ty1, _Ty2> { using type = _Common_ref_2AX_t<_Ty1, _Ty2>; }; @@ -1493,14 +1508,12 @@ template struct common_reference<_Ty1, _Ty2> : _Common_reference2A<_Ty1, _Ty2> {}; // N4950 [meta.trans.other]/5.4: "if sizeof...(T) is greater than two..." -template -struct _Fold_common_reference {}; -template -struct _Fold_common_reference>, _Ty1, _Ty2, _Types...> - : common_reference, _Types...> {}; - template -struct common_reference<_Ty1, _Ty2, _Ty3, _Rest...> : _Fold_common_reference {}; +struct common_reference<_Ty1, _Ty2, _Ty3, _Rest...> {}; +template + requires requires { typename common_reference_t<_Ty1, _Ty2>; } +struct common_reference<_Ty1, _Ty2, _Ty3, _Rest...> : common_reference, _Ty3, _Rest...> { +}; _EXPORT_STD template struct type_identity { diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 3342d9f1f..011c07227 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -2156,10 +2156,8 @@ _NODISCARD constexpr bool _Allocators_equal(const _Alloc& _Lhs, const _Alloc& _R } #if _HAS_CXX23 -template -constexpr bool _Has_member_from_primary = false; template -constexpr bool _Has_member_from_primary<_Ty, void_t> = true; +constexpr bool _Has_member_from_primary = requires { typename _Ty::_From_primary; }; // Avoid using allocate_at_least when the allocator publicly derives from std::allocator: // "old" allocators might hide allocate and deallocate but fail to hide allocate_at_least. @@ -2293,7 +2291,18 @@ template constexpr bool _Is_normally_bindable<_Ty, _Uty, void_t<_Normally_bound_ref<_Ty, _Uty>>> = true; #if _HAS_CXX20 -_EXPORT_STD template , int> = 0> +template +concept _Cv_std_pair = _Is_cv_pair<_Ty>; + +template +concept _Usable_for_pair_like_overload = +#if _HAS_CXX23 + _Pair_like<_Ty> || +#endif // _HAS_CXX23 + !_Is_deducible_as_pair<_Ty&>; + +_EXPORT_STD template + requires (!_Is_cv_pair<_Ty>) _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Types&&... _Args) noexcept { if constexpr (!uses_allocator_v, _Alloc>) { static_assert(is_constructible_v<_Ty, _Types...>, @@ -2313,39 +2322,33 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _T } } -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al) noexcept; -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty1&& _Val1, _Uty2&& _Val2) noexcept; #if _HAS_CXX23 -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>& _Pair) noexcept; #endif // _HAS_CXX23 -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept; -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>&& _Pair) noexcept; #if _HAS_CXX23 -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args( const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept; #endif // _HAS_CXX23 -#if _HAS_CXX23 -_EXPORT_STD template - requires _Is_cv_pair<_Ty> && (_Pair_like<_Uty> || !_Is_deducible_as_pair<_Uty&>) -#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv -_EXPORT_STD template && !_Is_deducible_as_pair<_Uty&>, int> = 0> -#endif // ^^^ !_HAS_CXX23 ^^^ +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, _Usable_for_pair_like_overload _Uty> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept; -_EXPORT_STD template , int> = 0> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Tuple1, class _Tuple2> _NODISCARD constexpr auto uses_allocator_construction_args( const _Alloc& _Al, piecewise_construct_t, _Tuple1&& _Tup1, _Tuple2&& _Tup2) noexcept { return _STD make_tuple(piecewise_construct, @@ -2363,7 +2366,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args( _STD forward<_Tuple2>(_Tup2))); } -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al) noexcept { // equivalent to // return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, tuple<>{}, tuple<>{}); @@ -2371,7 +2374,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al) no _STD uses_allocator_construction_args(_Al)); } -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty1&& _Val1, _Uty2&& _Val2) noexcept { // equivalent to // return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct, @@ -2382,7 +2385,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _U } #if _HAS_CXX23 -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _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, @@ -2393,7 +2396,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pa } #endif // _HAS_CXX23 -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args( const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept { // equivalent to @@ -2404,7 +2407,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args( _STD uses_allocator_construction_args(_Al, _Pair.second)); } -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _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, @@ -2415,7 +2418,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pa } #if _HAS_CXX23 -_EXPORT_STD template , int> /* = 0 */> +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, class _Uty1, class _Uty2> _NODISCARD constexpr auto uses_allocator_construction_args( const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept { // equivalent to @@ -2427,13 +2430,7 @@ _NODISCARD constexpr auto uses_allocator_construction_args( } #endif // _HAS_CXX23 -#if _HAS_CXX23 -_EXPORT_STD template - requires _Is_cv_pair<_Ty> && (_Pair_like<_Uty> || !_Is_deducible_as_pair<_Uty&>) -#else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv -_EXPORT_STD template && !_Is_deducible_as_pair<_Uty&>, int> /* = 0 */> -#endif // ^^^ !_HAS_CXX23 ^^^ +_EXPORT_STD template <_Cv_std_pair _Ty, class _Alloc, _Usable_for_pair_like_overload _Uty> _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept { #if _HAS_CXX23 if constexpr (_Pair_like<_Uty> && !_Is_subrange_v>) { diff --git a/stl/inc/xutility b/stl/inc/xutility index c22e4ba80..72b733a83 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -381,15 +381,10 @@ struct _Get_rebind_alias<_Ty, _Other, void_t(_STD declval<_Ty*>())) _Ty(_STD declval<_Types>()...))>> -#else // ^^^ no workaround / workaround vvv -// per LWG-3888 -_EXPORT_STD template (_STD declval<_Ty*>())) _Ty(_STD declval<_Types>()...))>* = nullptr> -#endif // ^^^ workaround ^^^ +_EXPORT_STD template + requires requires(_Ty* _Location, _Types&&... _Args) { + ::new (static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...); // per LWG-3888 + } constexpr _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( noexcept(::new(static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ { _MSVC_CONSTEXPR return ::new (static_cast(_Location)) _Ty(_STD forward<_Types>(_Args)...); @@ -711,8 +706,8 @@ _NODISCARD constexpr auto _Pass_fn(_Fn& _Func) noexcept { } #if _HAS_CXX23 -_EXPORT_STD template , int> = 0> +_EXPORT_STD template + requires is_invocable_r_v<_Result_type, _Callable, _Types...> _NODISCARD constexpr _Result_type invoke_r(_Callable&& _Obj, _Types&&... _Args) noexcept( is_nothrow_invocable_r_v<_Result_type, _Callable, _Types...>) { if constexpr (is_void_v<_Result_type>) { @@ -4330,7 +4325,8 @@ public: _Verify_range(_First._Current, _Last._Get_current()); } #if _HAS_CXX20 - template _Sent, enable_if_t<_Range_verifiable_v<_Iter, _Sent>, int> = 0> + template _Sent> + requires _Range_verifiable_v<_Iter, _Sent> friend constexpr void _Verify_range(const move_iterator& _First, const move_sentinel<_Sent>& _Last) noexcept { _Verify_range(_First._Current, _Last._Get_last()); }