Index: libcxx/include/CMakeLists.txt =================================================================== --- libcxx/include/CMakeLists.txt +++ libcxx/include/CMakeLists.txt @@ -98,6 +98,9 @@ __bsd_locale_defaults.h __bsd_locale_fallbacks.h __config + __compare/common_comparison_category.h + __compare/ordering.h + __compare/three_way_comparable.h __debug __errc __format/format_error.h Index: libcxx/include/__compare/common_comparison_category.h =================================================================== --- /dev/null +++ libcxx/include/__compare/common_comparison_category.h @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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___COMMON_COMPARISON_CATEGORY_H +#define _LIBCPP___COMMON_COMPARISON_CATEGORY_H + +#include <__config> +#include <__compare/ordering.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +namespace __comp_detail { + +enum _ClassifyCompCategory : unsigned{ + _None, + _PartialOrd, + _WeakOrd, + _StrongOrd, + _CCC_Size +}; + +template +_LIBCPP_INLINE_VISIBILITY +constexpr _ClassifyCompCategory __type_to_enum() noexcept { + if (is_same_v<_Tp, partial_ordering>) + return _PartialOrd; + if (is_same_v<_Tp, weak_ordering>) + return _WeakOrd; + if (is_same_v<_Tp, strong_ordering>) + return _StrongOrd; + return _None; +} + +template +constexpr _ClassifyCompCategory +__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { + int __seen[_CCC_Size] = {}; + for (auto __type : __types) + ++__seen[__type]; + if (__seen[_None]) + return _None; + if (__seen[_PartialOrd]) + return _PartialOrd; + if (__seen[_WeakOrd]) + return _WeakOrd; + return _StrongOrd; +} + +template +constexpr auto __get_comp_type() { + using _CCC = _ClassifyCompCategory; + constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; + constexpr _CCC _Cat = __compute_comp_type(__type_kinds); + if constexpr (_Cat == _None) + return void(); + else if constexpr (_Cat == _PartialOrd) + return partial_ordering::equivalent; + else if constexpr (_Cat == _WeakOrd) + return weak_ordering::equivalent; + else if constexpr (_Cat == _StrongOrd) + return strong_ordering::equivalent; + else + static_assert(_Cat != _Cat, "unhandled case"); +} +} // namespace __comp_detail + +// [cmp.common], common comparison category type +template +struct _LIBCPP_TEMPLATE_VIS common_comparison_category { + using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); +}; + +template +using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___COMMON_COMPARISON_CATEGORY_H Index: libcxx/include/__compare/ordering.h =================================================================== --- /dev/null +++ libcxx/include/__compare/ordering.h @@ -0,0 +1,313 @@ +//===----------------------------------------------------------------------===// +// +// 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_ORDERING_H +#define _LIBCPP___COMPARE_ORDERING_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) +// exposition only +enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char { + __zero = 0, + __equal = __zero, + __equiv = __equal, + __nonequal = 1, + __nonequiv = __nonequal +}; + +enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { + __less = -1, + __greater = 1 +}; + +enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { + __unordered = -127 +}; + +class partial_ordering; +class weak_ordering; +class strong_ordering; + +template +inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); + +struct _CmpUnspecifiedParam { + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL + _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} + + template>> + _CmpUnspecifiedParam(_Tp) = delete; +}; + +class partial_ordering { + using _ValueT = signed char; + + _LIBCPP_INLINE_VISIBILITY + explicit constexpr partial_ordering(_EqResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_INLINE_VISIBILITY + explicit constexpr partial_ordering(_OrdResult __v) noexcept + : __value_(_ValueT(__v)) {} + + _LIBCPP_INLINE_VISIBILITY + explicit constexpr partial_ordering(_NCmpResult __v) noexcept + : __value_(_ValueT(__v)) {} + + constexpr bool __is_ordered() const noexcept { + return __value_ != _ValueT(_NCmpResult::__unordered); + } +public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ == 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ < 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ <= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ > 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ >= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 < __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 <= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 > __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 >= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); + } +private: + _ValueT __value_; +}; + +_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less); +_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv); +_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); +_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); + +class weak_ordering { + using _ValueT = signed char; + + _LIBCPP_INLINE_VISIBILITY + explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} + _LIBCPP_INLINE_VISIBILITY + explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + _LIBCPP_INLINE_VISIBILITY + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + // comparisons + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less); +_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); +_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); +class strong_ordering { + using _ValueT = signed char; + + _LIBCPP_INLINE_VISIBILITY + explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} + _LIBCPP_INLINE_VISIBILITY + explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + // conversions + _LIBCPP_INLINE_VISIBILITY + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr operator weak_ordering() const noexcept { + return __value_ == 0 ? weak_ordering::equivalent + : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); + } + + // comparisons + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 < __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 <= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 > __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 >= __v.__value_; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; + } + + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); + } + +private: + _ValueT __value_; +}; + +_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less); +_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal); +_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); +_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); + +// named comparison functions +_LIBCPP_INLINE_VISIBILITY +constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } + +_LIBCPP_INLINE_VISIBILITY +constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; } + +_LIBCPP_INLINE_VISIBILITY +constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; } + +_LIBCPP_INLINE_VISIBILITY +constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; } + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___COMPARE_ORDERING_H Index: libcxx/include/__compare/three_way_comparable.h =================================================================== --- /dev/null +++ libcxx/include/__compare/three_way_comparable.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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___THREE_WAY_COMPARABLE_H +#define _LIBCPP___THREE_WAY_COMPARABLE_H + +#include <__config> +#include <__compare/common_comparison_category.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +template +concept __compares_as = // exposition only + same_as, _Cat>; + +template +concept three_way_comparable = + __weakly_equality_comparable_with<_Tp, _Tp> && + __partially_ordered_with<_Tp, _Tp> && + requires(__make_const_lvalue_ref<_Tp> __a, __make_const_lvalue_ref<_Tp> __b) { + { __a <=> __b } -> __compares_as<_Cat>; + }; + +template +concept three_way_comparable_with = + three_way_comparable<_Tp, _Cat> && + three_way_comparable<_Up, _Cat> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + three_way_comparable< + common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> && + __weakly_equality_comparable_with<_Tp, _Up> && + __partially_ordered_with<_Tp, _Up> && + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t <=> __u } -> __compares_as<_Cat>; + { __u <=> __t } -> __compares_as<_Cat>; + }; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___THREE_WAY_COMPARABLE_H Index: libcxx/include/compare =================================================================== --- libcxx/include/compare +++ libcxx/include/compare @@ -121,360 +121,21 @@ */ #include <__config> +#include <__compare/common_comparison_category.h> +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) -// exposition only -enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char { - __zero = 0, - __equal = __zero, - __equiv = __equal, - __nonequal = 1, - __nonequiv = __nonequal -}; - -enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { - __less = -1, - __greater = 1 -}; - -enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { - __unordered = -127 -}; - -class partial_ordering; -class weak_ordering; -class strong_ordering; - -template -inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); - -struct _CmpUnspecifiedParam { - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL - _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} - - template>> - _CmpUnspecifiedParam(_Tp) = delete; -}; - -class partial_ordering { - using _ValueT = signed char; - - _LIBCPP_INLINE_VISIBILITY - explicit constexpr partial_ordering(_EqResult __v) noexcept - : __value_(_ValueT(__v)) {} - - _LIBCPP_INLINE_VISIBILITY - explicit constexpr partial_ordering(_OrdResult __v) noexcept - : __value_(_ValueT(__v)) {} - - _LIBCPP_INLINE_VISIBILITY - explicit constexpr partial_ordering(_NCmpResult __v) noexcept - : __value_(_ValueT(__v)) {} - - constexpr bool __is_ordered() const noexcept { - return __value_ != _ValueT(_NCmpResult::__unordered); - } -public: - // valid values - static const partial_ordering less; - static const partial_ordering equivalent; - static const partial_ordering greater; - static const partial_ordering unordered; - - // comparisons - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__is_ordered() && __v.__value_ == 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__is_ordered() && __v.__value_ < 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__is_ordered() && __v.__value_ <= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__is_ordered() && __v.__value_ > 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__is_ordered() && __v.__value_ >= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { - return __v.__is_ordered() && 0 < __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { - return __v.__is_ordered() && 0 <= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { - return __v.__is_ordered() && 0 > __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { - return __v.__is_ordered() && 0 >= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { - return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); - } -private: - _ValueT __value_; -}; - -_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less); -_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv); -_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); -_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); - -class weak_ordering { - using _ValueT = signed char; - - _LIBCPP_INLINE_VISIBILITY - explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} - _LIBCPP_INLINE_VISIBILITY - explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} - -public: - static const weak_ordering less; - static const weak_ordering equivalent; - static const weak_ordering greater; - - _LIBCPP_INLINE_VISIBILITY - constexpr operator partial_ordering() const noexcept { - return __value_ == 0 ? partial_ordering::equivalent - : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); - } - - // comparisons - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ == 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ < 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ <= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ > 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ >= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { - return 0 < __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { - return 0 <= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { - return 0 > __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { - return 0 >= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { - return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); - } - -private: - _ValueT __value_; -}; - -_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less); -_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); -_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); -class strong_ordering { - using _ValueT = signed char; - - _LIBCPP_INLINE_VISIBILITY - explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} - _LIBCPP_INLINE_VISIBILITY - explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} - -public: - static const strong_ordering less; - static const strong_ordering equal; - static const strong_ordering equivalent; - static const strong_ordering greater; - - // conversions - _LIBCPP_INLINE_VISIBILITY - constexpr operator partial_ordering() const noexcept { - return __value_ == 0 ? partial_ordering::equivalent - : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); - } - - _LIBCPP_INLINE_VISIBILITY - constexpr operator weak_ordering() const noexcept { - return __value_ == 0 ? weak_ordering::equivalent - : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); - } - - // comparisons - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ == 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ < 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ <= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ > 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v.__value_ >= 0; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { - return 0 < __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { - return 0 <= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { - return 0 > __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { - return 0 >= __v.__value_; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { - return __v; - } - - _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { - return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); - } - -private: - _ValueT __value_; -}; - -_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less); -_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal); -_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); -_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); - -// named comparison functions -_LIBCPP_INLINE_VISIBILITY -constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } - -_LIBCPP_INLINE_VISIBILITY -constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; } - -_LIBCPP_INLINE_VISIBILITY -constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; } - -_LIBCPP_INLINE_VISIBILITY -constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; } - -namespace __comp_detail { - -enum _ClassifyCompCategory : unsigned{ - _None, - _PartialOrd, - _WeakOrd, - _StrongOrd, - _CCC_Size -}; - -template -_LIBCPP_INLINE_VISIBILITY -constexpr _ClassifyCompCategory __type_to_enum() noexcept { - if (is_same_v<_Tp, partial_ordering>) - return _PartialOrd; - if (is_same_v<_Tp, weak_ordering>) - return _WeakOrd; - if (is_same_v<_Tp, strong_ordering>) - return _StrongOrd; - return _None; -} - -template -constexpr _ClassifyCompCategory -__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { - int __seen[_CCC_Size] = {}; - for (auto __type : __types) - ++__seen[__type]; - if (__seen[_None]) - return _None; - if (__seen[_PartialOrd]) - return _PartialOrd; - if (__seen[_WeakOrd]) - return _WeakOrd; - return _StrongOrd; -} - -template -constexpr auto __get_comp_type() { - using _CCC = _ClassifyCompCategory; - constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; - constexpr _CCC _Cat = __compute_comp_type(__type_kinds); - if constexpr (_Cat == _None) - return void(); - else if constexpr (_Cat == _PartialOrd) - return partial_ordering::equivalent; - else if constexpr (_Cat == _WeakOrd) - return weak_ordering::equivalent; - else if constexpr (_Cat == _StrongOrd) - return strong_ordering::equivalent; - else - static_assert(_Cat != _Cat, "unhandled case"); -} -} // namespace __comp_detail - -// [cmp.common], common comparison category type -template -struct _LIBCPP_TEMPLATE_VIS common_comparison_category { - using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); -}; - -template -using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; // [cmp.alg], comparison algorithms // TODO: unimplemented @@ -486,4 +147,6 @@ _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP_COMPARE Index: libcxx/include/utility =================================================================== --- libcxx/include/utility +++ libcxx/include/utility @@ -223,7 +223,9 @@ #include <__utility/rel_ops.h> #include <__utility/swap.h> #include <__utility/to_underlying.h> -#include +// FIXME (rarutyun): return back include when +// cyclic dependency for this header is resolved +// #include #include #include Index: libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp =================================================================== --- libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp +++ libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp @@ -22,7 +22,9 @@ # error " was expected to define _LIBCPP_UTILITY" #endif #if TEST_STD_VER > 17 && !defined(_LIBCPP_COMPARE) - # error " should include in C++20 and later" +// FIXME (rarutyun): enable this test part when cyclic dependency for +// header is resolved +// # error " should include in C++20 and later" #endif #if TEST_STD_VER > 03 && !defined(_LIBCPP_INITIALIZER_LIST) # error " should include in C++11 and later" Index: libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable.compile.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable.compile.pass.cpp @@ -0,0 +1,230 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept three_way_comparable = // see below + +#include + +#include "compare_types.h" + +namespace fundamentals { +// with default ordering +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +#ifndef _LIBCPP_HAS_NO_CHAR8_T +static_assert(std::three_way_comparable); +#endif +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +#endif +#ifndef _LIBCPP_HAS_NO_INT128 +static_assert(std::three_way_comparable<__int128_t const&>); +static_assert(std::three_way_comparable<__uint128_t const&>); +#endif +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); + +// with explicit ordering +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); + +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); + +struct S {}; +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert(!std::three_way_comparable); +static_assert( + !std::three_way_comparable); + +static_assert(!std::three_way_comparable); +} // namespace fundamentals + +namespace user_defined { + +struct S { + auto operator<=>(const S&) const = default; +}; + +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); +static_assert(std::three_way_comparable); + +struct SpaceshipNotDeclared { +}; + +static_assert(!std::three_way_comparable); + +struct SpaceshipDeleted { + auto operator<=>(const SpaceshipDeleted&) const = delete; +}; + +static_assert(!std::three_way_comparable); + +struct SpaceshipWithoutEqualityOperator { + auto operator<=>(const SpaceshipWithoutEqualityOperator&) const; +}; + +static_assert(!std::three_way_comparable); + +struct EqualityOperatorDeleted { + bool operator==(const EqualityOperatorDeleted&) const = delete; +}; + +static_assert(!std::three_way_comparable); + +struct EqualityOperatorOnly { + bool operator==(const EqualityOperatorOnly&) const = default; +}; + +static_assert(!std::three_way_comparable); + +struct SpaceshipDeclaredEqualityOperatorDeleted { + bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete; + auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default; +}; + +static_assert(!std::three_way_comparable); + +struct AllInequalityOperators { + bool operator<(const AllInequalityOperators&) const; + bool operator<=(const AllInequalityOperators&) const; + bool operator>(const AllInequalityOperators&) const; + bool operator>=(const AllInequalityOperators&) const; + bool operator!=(const AllInequalityOperators&) const; +}; + +static_assert(!std::three_way_comparable); + +struct AllComparisonOperators { + bool operator<(const AllComparisonOperators&) const; + bool operator<=(const AllComparisonOperators&) const; + bool operator>(const AllComparisonOperators&) const; + bool operator>=(const AllComparisonOperators&) const; + bool operator!=(const AllComparisonOperators&) const; + bool operator==(const AllComparisonOperators&) const; +}; + +static_assert(!std::three_way_comparable); + +struct AllButOneInequalityOperators { + bool operator<(const AllButOneInequalityOperators&) const; + bool operator<=(const AllButOneInequalityOperators&) const; + bool operator>(const AllButOneInequalityOperators&) const; + bool operator!=(const AllButOneInequalityOperators&) const; +}; + +static_assert(!std::three_way_comparable); + +struct AllInequalityOperatorsOneDeleted { + bool operator<(const AllInequalityOperatorsOneDeleted&) const; + bool operator<=(const AllInequalityOperatorsOneDeleted&) const; + bool operator>(const AllInequalityOperatorsOneDeleted&) const; + bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete; + bool operator!=(const AllInequalityOperatorsOneDeleted&) const; +}; + +static_assert(!std::three_way_comparable); + +struct EqualityOperatorWrongReturnType { + int operator==(const EqualityOperatorWrongReturnType&); + auto operator<=>(const EqualityOperatorWrongReturnType&) const = default; +}; + +static_assert(!std::three_way_comparable); + +struct SpaceshipWrongReturnType { + bool operator==(const SpaceshipWrongReturnType&) const = default; + int operator<=>(const SpaceshipWrongReturnType&); +}; + +static_assert(!std::three_way_comparable); + +struct EqualityOperatorNonConstArgument { + bool operator==(EqualityOperatorNonConstArgument&); + auto operator<=>(const EqualityOperatorNonConstArgument&) const = default; +}; + +static_assert(!std::three_way_comparable); + +struct SpaceshipNonConstArgument { + bool operator==(const SpaceshipNonConstArgument&) const = default; + auto operator<=>(SpaceshipNonConstArgument&); +}; + +static_assert(!std::three_way_comparable); +} + +int main(int, char**) { return 0; } Index: libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp @@ -0,0 +1,242 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept three_way_comparable_with = // see below + +#include + +#include "compare_types.h" + +template +constexpr bool check_three_way_comparable_with() { + constexpr bool result = std::three_way_comparable_with; + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + if constexpr (!std::is_void_v) { + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + static_assert(std::three_way_comparable_with == result); + } + return result; +} + +namespace fundamentals { +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); + +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); + +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); + +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +struct S {}; +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with< + int, int (S::*)() const volatile noexcept>()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert( + !check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with < int, + int (S::*)() && noexcept > ()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with < int, + int (S::*)() const&& noexcept > ()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with < int, + int (S::*)() volatile&& noexcept > ()); +static_assert( + !check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with < int, + int (S::*)() const volatile&& noexcept > ()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +static_assert(!check_three_way_comparable_with()); +} + +namespace user_defined { +struct S { + bool operator==(int) const; + std::strong_ordering operator<=>(int) const; + operator int() const; + + bool operator==(const S&) const = default; + auto operator<=>(const S&) const = default; +}; + +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); +static_assert(check_three_way_comparable_with()); + +struct SpaceshipNotDeclared { +}; + +static_assert(!check_three_way_comparable_with()); + +struct SpaceshipDeleted { + auto operator<=>(const SpaceshipDeleted&) const = delete; +}; + +static_assert(!check_three_way_comparable_with()); + +struct SpaceshipWithoutEqualityOperator { + auto operator<=>(const SpaceshipWithoutEqualityOperator&) const; +}; + +static_assert(!check_three_way_comparable_with()); + +struct EqualityOperatorDeleted { + bool operator==(const EqualityOperatorDeleted&) const = delete; +}; + +static_assert(!check_three_way_comparable_with()); + +struct EqualityOperatorOnly { + bool operator==(const EqualityOperatorOnly&) const = default; +}; + +static_assert(!check_three_way_comparable_with()); + +struct SpaceshipDeclaredEqualityOperatorDeleted { + bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete; + auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default; +}; + +static_assert(!check_three_way_comparable_with()); + +struct AllInequalityOperators { + bool operator<(const AllInequalityOperators&) const; + bool operator<=(const AllInequalityOperators&) const; + bool operator>(const AllInequalityOperators&) const; + bool operator>=(const AllInequalityOperators&) const; + bool operator!=(const AllInequalityOperators&) const; +}; + +static_assert(!check_three_way_comparable_with()); + +struct AllComparisonOperators { + bool operator<(const AllComparisonOperators&) const; + bool operator<=(const AllComparisonOperators&) const; + bool operator>(const AllComparisonOperators&) const; + bool operator>=(const AllComparisonOperators&) const; + bool operator!=(const AllComparisonOperators&) const; + bool operator==(const AllComparisonOperators&) const; +}; + +static_assert(!check_three_way_comparable_with()); + +struct AllButOneInequalityOperators { + bool operator<(const AllButOneInequalityOperators&) const; + bool operator<=(const AllButOneInequalityOperators&) const; + bool operator>(const AllButOneInequalityOperators&) const; + bool operator!=(const AllButOneInequalityOperators&) const; +}; + +static_assert(!check_three_way_comparable_with()); + +struct AllInequalityOperatorsOneDeleted { + bool operator<(const AllInequalityOperatorsOneDeleted&) const; + bool operator<=(const AllInequalityOperatorsOneDeleted&) const; + bool operator>(const AllInequalityOperatorsOneDeleted&) const; + bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete; + bool operator!=(const AllInequalityOperatorsOneDeleted&) const; +}; + +static_assert(!check_three_way_comparable_with()); + +struct EqualityOperatorWrongReturnType { + int operator==(const EqualityOperatorWrongReturnType&); + auto operator<=>(const EqualityOperatorWrongReturnType&) const = default; +}; + +static_assert(!check_three_way_comparable_with()); + +struct SpaceshipWrongReturnType { + bool operator==(const SpaceshipWrongReturnType&) const = default; + int operator<=>(const SpaceshipWrongReturnType&); +}; + +static_assert(!check_three_way_comparable_with()); + +struct EqualityOperatorNonConstArgument { + bool operator==(EqualityOperatorNonConstArgument&); + auto operator<=>(const EqualityOperatorNonConstArgument&) const = default; +}; + +static_assert(!check_three_way_comparable_with()); + +struct SpaceshipNonConstArgument { + bool operator==(const SpaceshipNonConstArgument&) const = default; + auto operator<=>(SpaceshipNonConstArgument&); +}; + +static_assert(!check_three_way_comparable_with()); +} + +int main(int, char**) { return 0; }