diff --git a/libcxx/include/compare b/libcxx/include/compare --- a/libcxx/include/compare +++ b/libcxx/include/compare @@ -121,6 +121,7 @@ */ #include <__config> +#include #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER @@ -482,6 +483,32 @@ template constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); template constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); +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 diff --git a/libcxx/include/utility b/libcxx/include/utility --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -211,7 +211,9 @@ #include <__debug> #include <__tuple> #include <__utility/to_underlying.h> -#include +// FIXME (rarutyun): return back include when +// cyclic dependency for this header is resolved +// #include #include #include #include diff --git a/libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp b/libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp --- a/libcxx/test/libcxx/inclusions/utility.inclusions.compile.pass.cpp +++ b/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" diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable.compile.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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); +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); + +// 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); +} + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp @@ -0,0 +1,138 @@ +//===----------------------------------------------------------------------===// +// +// 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()); +} + +int main(int, char**) { return 0; }