diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -97,8 +97,10 @@ __bits __bsd_locale_defaults.h __bsd_locale_fallbacks.h + __compare/__synthesized.h # NOT FOR REVIEW __compare/common_comparison_category.h __compare/ordering.h + __concepts/comparison.h # NOT FOR REVIEW __config __debug __errc diff --git a/libcxx/include/__compare/__synthesized.h b/libcxx/include/__compare/__synthesized.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__compare/__synthesized.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE___SYNTHESIZED_H +#define _LIBCPP___COMPARE___SYNTHESIZED_H + +#include <__config> +#include <__compare/ordering.h> +#include <__concepts/comparison.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +template +constexpr auto __synth_three_way(const T& __t, const U& __u) + requires requires { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } +{ + if constexpr (three_way_comparable_with) { + return __t <=> __u; + } else { + if (__t < __u) return weak_ordering::less; + if (__u < __t) return weak_ordering::greater; + return weak_ordering::equivalent; + } +} + +template +using __synth_three_way_result = decltype(__synth_three_way(declval(), declval())); + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE___SYNTHESIZED_H diff --git a/libcxx/include/__concepts/comparison.h b/libcxx/include/__concepts/comparison.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/comparison.h @@ -0,0 +1,138 @@ +// THIS FILE NOT FOR REVIEW (see: https://reviews.llvm.org/D107584 ) +#ifndef INCLUDE___CONCEPTS_COMPARISON_H_ +#define INCLUDE___CONCEPTS_COMPARISON_H_ + +#include <__config> +#include <__compare/common_comparison_category.h> +#include <__utility/forward.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.same] + +template +concept __same_as_impl = _IsSame<_Tp, _Up>::value; + +template +concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; + +// [concept.convertible] +template +concept convertible_to = + is_convertible_v<_From, _To> && + requires(add_rvalue_reference_t<_From> (&__f)()) { + static_cast<_To>(__f()); + }; + +// [concept.commonref] +template +concept common_reference_with = + same_as, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && + convertible_to<_Up, common_reference_t<_Tp, _Up>>; + +// [concept.booleantestable] +template +concept __boolean_testable_impl = convertible_to<_Tp, bool>; + +template +concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { + { !_VSTD::forward<_Tp>(__t) } -> __boolean_testable_impl; +}; + +// [concept.equalitycomparable] +template +concept __weakly_equality_comparable_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + +template +concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; + +template +concept equality_comparable_with = + equality_comparable<_Tp> && equality_comparable<_Up> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + equality_comparable< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __weakly_equality_comparable_with<_Tp, _Up>; + +// [concept.totallyordered] + +template +concept __partially_ordered_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + +template +concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; + +template +concept totally_ordered_with = + totally_ordered<_Tp> && totally_ordered<_Up> && + equality_comparable_with<_Tp, _Up> && + totally_ordered< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __partially_ordered_with<_Tp, _Up>; + + +// NOT FOR REVIEW +#if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +template +concept __compares_as = + same_as, Cat>; + +template +concept three_way_comparable = + __weakly_equality_comparable_with && + __partially_ordered_with && + requires(const remove_reference_t& a, const remove_reference_t& b) { + { a <=> b } -> __compares_as; + }; + +template +concept three_way_comparable_with = + three_way_comparable && + three_way_comparable && + common_reference_with&, const remove_reference_t&> && + three_way_comparable< + common_reference_t&, const remove_reference_t&>, Cat> && + __weakly_equality_comparable_with && + __partially_ordered_with && + requires(const remove_reference_t& t, const remove_reference_t& u) { + { t <=> u } -> __compares_as; + { u <=> t } -> __compares_as; + }; + +#endif // !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) +// end NOT FOR REVIEW + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif //INCLUDE___CONCEPTS_COMPARISON_H_ diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -10,6 +10,8 @@ #define _LIBCPP___UTILITY_PAIR_H #include <__config> +#include <__compare/__synthesized.h> +#include <__compare/common_comparison_category.h> #include <__functional/unwrap_ref.h> #include <__tuple> #include <__utility/forward.h> @@ -323,6 +325,22 @@ return __x.first == __y.first && __x.second == __y.second; } +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +common_comparison_category_t< + __synth_three_way_result<_T1>, + __synth_three_way_result<_T2> > +operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +{ + auto __result = __synth_three_way(__x.first, __y.first); + if (__result == 0) return __synth_three_way(__x.second, __y.second); + else return __result; +} + +#else // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool @@ -363,6 +381,8 @@ return !(__y < __x); } +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// CHANGES IN THIS FILE NOT FOR REVIEW + #ifndef _LIBCPP_CONCEPTS #define _LIBCPP_CONCEPTS @@ -130,6 +132,7 @@ */ #include <__config> +#include <__concepts/comparison.h> #include <__functional/invoke.h> #include <__functional_base> #include @@ -147,35 +150,12 @@ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) -// [concept.same] - -template -concept __same_as_impl = _IsSame<_Tp, _Up>::value; - -template -concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; - // [concept.derived] template concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v; -// [concept.convertible] -template -concept convertible_to = - is_convertible_v<_From, _To> && - requires(add_rvalue_reference_t<_From> (&__f)()) { - static_cast<_To>(__f()); - }; - -// [concept.commonref] -template -concept common_reference_with = - same_as, common_reference_t<_Up, _Tp>> && - convertible_to<_Tp, common_reference_t<_Tp, _Up>> && - convertible_to<_Up, common_reference_t<_Tp, _Up>>; - // [concept.common] template concept common_with = @@ -332,66 +312,6 @@ ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); }; -// [concept.booleantestable] -template -concept __boolean_testable_impl = convertible_to<_Tp, bool>; - -template -concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { - { !std::forward<_Tp>(__t) } -> __boolean_testable_impl; -}; - -// [concept.equalitycomparable] -template -concept __weakly_equality_comparable_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t == __u } -> __boolean_testable; - { __t != __u } -> __boolean_testable; - { __u == __t } -> __boolean_testable; - { __u != __t } -> __boolean_testable; - }; - -template -concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; - -template -concept equality_comparable_with = - equality_comparable<_Tp> && equality_comparable<_Up> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && - equality_comparable< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __weakly_equality_comparable_with<_Tp, _Up>; - -// [concept.totallyordered] - -template -concept __partially_ordered_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t < __u } -> __boolean_testable; - { __t > __u } -> __boolean_testable; - { __t <= __u } -> __boolean_testable; - { __t >= __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - { __u > __t } -> __boolean_testable; - { __u <= __t } -> __boolean_testable; - { __u >= __t } -> __boolean_testable; - }; - -template -concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; - -template -concept totally_ordered_with = - totally_ordered<_Tp> && totally_ordered<_Up> && - equality_comparable_with<_Tp, _Up> && - totally_ordered< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __partially_ordered_with<_Tp, _Up>; - // [concepts.object] template concept movable =