diff --git a/libcxx/include/compare b/libcxx/include/compare --- a/libcxx/include/compare +++ b/libcxx/include/compare @@ -482,6 +482,23 @@ template constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); template constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); +// [cmp.result], result of three-way comparison +template +using __compare_three_way_result_type = decltype(declval<__make_const_lvalue_ref<_Tp>>() <=> + declval<__make_const_lvalue_ref<_Up>>()); + +template +struct compare_three_way_result {}; + +template + requires requires { typename __compare_three_way_result_type<_Tp, _Up>; } +struct compare_three_way_result<_Tp, _Up> { + using type = __compare_three_way_result_type<_Tp, _Up>; +}; + +template +using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; + #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/language.support/cmp/cmp.result/compare_three_way_result.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.result/compare_three_way_result.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/cmp/cmp.result/compare_three_way_result.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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++98, c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// + +// compare_three_way_result, compare_three_way_result_t + +#include +#include + +template +concept compare_three_way_result_type_defined = requires { + typename std::compare_three_way_result::type; +}; + +template +concept compare_three_way_result_t_defined = requires { + typename std::compare_three_way_result_t; +}; + +struct OtherOperand { + friend std::strong_ordering operator<=>( const OtherOperand&, const OtherOperand& ) = delete; +}; + +template +struct Operand { + SameOperandsOrdering operator<=>( const Operand& ) const = default; + friend DifferentOperandsOrdering operator<=>( const Operand&, const OtherOperand& ) { + return DifferentOperandsOrdering::equivalent; + } +}; + +template +constexpr void do_compare_three_way_result_positive_test() { + using OperandType = Operand; + static_assert(std::is_same_v, SameOperandsOrdering>); + static_assert(std::is_same_v, SameOperandsOrdering>); + static_assert(std::is_same_v, std::add_lvalue_reference_t>, + SameOperandsOrdering>); + static_assert(std::is_same_v, DifferentOperandsOrdering>); + static_assert(std::is_same_v, DifferentOperandsOrdering>); + static_assert(std::is_same_v, std::add_lvalue_reference_t>, + DifferentOperandsOrdering>); + + static_assert(std::is_same_v, + typename std::compare_three_way_result::type>); + static_assert(std::is_same_v, + typename std::compare_three_way_result::type>); + static_assert(std::is_same_v, + typename std::compare_three_way_result::type>); + static_assert(std::is_same_v, + typename std::compare_three_way_result::type>); + static_assert(std::is_same_v, + std::add_lvalue_reference_t>, + typename std::compare_three_way_result::type>); +} + +constexpr void do_compare_three_way_result_negative_test() { + static_assert(!compare_three_way_result_type_defined); + static_assert(!compare_three_way_result_type_defined); + static_assert(!compare_three_way_result_type_defined); + + static_assert(!compare_three_way_result_t_defined); + static_assert(!compare_three_way_result_t_defined); + static_assert(!compare_three_way_result_t_defined); +} + +int main(int, char**) { + do_compare_three_way_result_positive_test(); + do_compare_three_way_result_positive_test(); + do_compare_three_way_result_positive_test(); + do_compare_three_way_result_negative_test(); +}