diff --git a/libcxx/include/__type_traits/desugars_to.h b/libcxx/include/__type_traits/desugars_to.h index b67baae31b181..029b3c6336837 100644 --- a/libcxx/include/__type_traits/desugars_to.h +++ b/libcxx/include/__type_traits/desugars_to.h @@ -10,6 +10,7 @@ #define _LIBCPP___TYPE_TRAITS_DESUGARS_TO_H #include <__config> +#include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -64,6 +65,9 @@ template inline const bool __desugars_to_v<_CanonicalTag, _Operation&&, _Args...> = __desugars_to_v<_CanonicalTag, _Operation, _Args...>; +template +struct __desugars_to : integral_constant > {}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_DESUGARS_TO_H diff --git a/libcxx/include/__utility/default_three_way_comparator.h b/libcxx/include/__utility/default_three_way_comparator.h index ce423c6ce98e4..438ab55b43230 100644 --- a/libcxx/include/__utility/default_three_way_comparator.h +++ b/libcxx/include/__utility/default_three_way_comparator.h @@ -27,9 +27,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __default_three_way_comparator; -template -struct __default_three_way_comparator<_Tp, _Tp, __enable_if_t::value> > { - _LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) { +template +struct __default_three_way_comparator<_LHS, + _RHS, + __enable_if_t::value && is_arithmetic<_RHS>::value> > { + _LIBCPP_HIDE_FROM_ABI static int operator()(_LHS __lhs, _RHS __rhs) { if (__lhs < __rhs) return -1; if (__lhs > __rhs) @@ -38,12 +40,30 @@ struct __default_three_way_comparator<_Tp, _Tp, __enable_if_t } }; +#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_lt_synthesises_from_spaceship) +template +struct __default_three_way_comparator< + _LHS, + _RHS, + __enable_if_t::value && is_arithmetic<_RHS>::value) && + __builtin_lt_synthesises_from_spaceship(const _LHS&, const _RHS&)>> { + _LIBCPP_HIDE_FROM_ABI static int operator()(const _LHS& __lhs, const _RHS& __rhs) { + auto __res = __lhs <=> __rhs; + if (__res < 0) + return -1; + if (__res > 0) + return 1; + return 0; + } +}; +#endif + template -inline const bool __has_default_three_way_comparator_v = false; +struct __has_default_three_way_comparator : false_type {}; template -inline const bool - __has_default_three_way_comparator_v< _LHS, _RHS, sizeof(__default_three_way_comparator<_LHS, _RHS>) >= 0> = true; +struct __has_default_three_way_comparator<_LHS, _RHS, sizeof(__default_three_way_comparator<_LHS, _RHS>) >= 0> + : true_type {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/lazy_synth_three_way_comparator.h b/libcxx/include/__utility/lazy_synth_three_way_comparator.h index ca98845f04191..9105d05e1ed6a 100644 --- a/libcxx/include/__utility/lazy_synth_three_way_comparator.h +++ b/libcxx/include/__utility/lazy_synth_three_way_comparator.h @@ -10,6 +10,7 @@ #define _LIBCPP___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H #include <__config> +#include <__type_traits/conjunction.h> #include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__utility/default_three_way_comparator.h> @@ -69,11 +70,12 @@ struct __eager_compare_result { }; template -struct __lazy_synth_three_way_comparator<_Comparator, - _LHS, - _RHS, - __enable_if_t<__desugars_to_v<__less_tag, _Comparator, _LHS, _RHS> && - __has_default_three_way_comparator_v<_LHS, _RHS> > > { +struct __lazy_synth_three_way_comparator< + _Comparator, + _LHS, + _RHS, + __enable_if_t<_And<__desugars_to<__less_tag, _Comparator, _LHS, _RHS>, + __has_default_three_way_comparator<_LHS, _RHS> >::value> > { // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of // the comparator. _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} diff --git a/libcxx/include/string b/libcxx/include/string index 0abdfebcb863f..f13a7640760f7 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -2521,6 +2521,7 @@ _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif # undef _LIBCPP_DECLARE +# if _LIBCPP_STD_VER <= 17 || !__has_builtin(__builtin_lt_synthesises_from_spaceship) template struct __default_three_way_comparator, basic_string<_CharT, _Traits, _Alloc> > { using __string_t _LIBCPP_NODEBUG = basic_string<_CharT, _Traits, _Alloc>; @@ -2533,6 +2534,7 @@ struct __default_three_way_comparator, bas return __ret; } }; +# endif # if _LIBCPP_STD_VER >= 17 template +#include +#include + +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); + +#if __has_builtin(__builtin_lt_synthesises_from_spaceship) +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(std::__has_default_three_way_comparator::value); +static_assert(!std::__has_default_three_way_comparator::value); + +static_assert(std::__has_default_three_way_comparator&, const std::vector&>::value); + +struct MyStruct { + int i; + + friend auto operator<=>(MyStruct, MyStruct) = default; +}; + +static_assert(std::__has_default_three_way_comparator::value); +#endif