1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // <compare>
12 
13 // template<class T, class U = T> struct compare_three_way_result;
14 // template<class T, class U = T>
15 //   using compare_three_way_result_t = typename compare_three_way_result<T, U>::type;
16 
17 #include <compare>
18 
19 #include "test_macros.h"
20 
21 template<class T>
22 concept has_no_nested_type = !requires { typename T::type; };
23 
24 ASSERT_SAME_TYPE(std::compare_three_way_result_t<int>, std::strong_ordering);
25 ASSERT_SAME_TYPE(std::compare_three_way_result_t<float>, std::partial_ordering);
26 ASSERT_SAME_TYPE(std::compare_three_way_result_t<unsigned>, std::strong_ordering);
27 
28 ASSERT_SAME_TYPE(std::compare_three_way_result_t<int, int>, std::strong_ordering);
29 ASSERT_SAME_TYPE(std::compare_three_way_result_t<int, float>, std::partial_ordering);
30 ASSERT_SAME_TYPE(std::compare_three_way_result_t<float, int>, std::partial_ordering);
31 ASSERT_SAME_TYPE(std::compare_three_way_result_t<float, float>, std::partial_ordering);
32 ASSERT_SAME_TYPE(std::compare_three_way_result_t<float, unsigned>, std::partial_ordering);
33 ASSERT_SAME_TYPE(std::compare_three_way_result_t<unsigned, float>, std::partial_ordering);
34 ASSERT_SAME_TYPE(std::compare_three_way_result_t<unsigned, unsigned>, std::strong_ordering);
35 
36 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const int&>, std::strong_ordering);
37 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const int&, int>, std::strong_ordering);
38 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const int*>, std::strong_ordering);
39 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const int*, int*>, std::strong_ordering);
40 
41 static_assert(has_no_nested_type<std::compare_three_way_result<void>>);
42 static_assert(has_no_nested_type<std::compare_three_way_result<void, void>>);
43 static_assert(has_no_nested_type<std::compare_three_way_result<int, void>>);
44 static_assert(has_no_nested_type<std::compare_three_way_result<int, int*>>);
45 static_assert(has_no_nested_type<std::compare_three_way_result<int, unsigned>>);
46 static_assert(has_no_nested_type<std::compare_three_way_result<unsigned, int>>);
47 
48 struct A {
49     float operator<=>(const A&) const;  // a non-comparison-category type is OK
50 };
51 ASSERT_SAME_TYPE(std::compare_three_way_result_t<A>, float);
52 ASSERT_SAME_TYPE(std::compare_three_way_result_t<A, A>, float);
53 
54 struct B {
55     using T = int(&)();
56     T operator<=>(const B&) const;  // no decay takes place either
57 };
58 ASSERT_SAME_TYPE(std::compare_three_way_result_t<B>, int(&)());
59 ASSERT_SAME_TYPE(std::compare_three_way_result_t<B, B>, int(&)());
60 
61 struct C {
62     std::strong_ordering operator<=>(C&);  // C isn't const-comparable
63 };
64 static_assert(has_no_nested_type<std::compare_three_way_result<C>>);
65 static_assert(has_no_nested_type<std::compare_three_way_result<C&>>);
66 static_assert(has_no_nested_type<std::compare_three_way_result<C&&>>);
67 
68 static_assert(has_no_nested_type<std::compare_three_way_result<C, C>>);
69 static_assert(has_no_nested_type<std::compare_three_way_result<C&, C&>>);
70 static_assert(has_no_nested_type<std::compare_three_way_result<C&&, C&&>>);
71 
72 struct D {
73     std::strong_ordering operator<=>(D&) &;
74     std::strong_ordering operator<=>(D&&) &&;
75     std::weak_ordering operator<=>(const D&) const&;  // comparison is always done by const&
76     std::strong_ordering operator<=>(const D&&) const&&;
77 };
78 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D>, std::weak_ordering);
79 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D&>, std::weak_ordering);
80 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D&&>, std::weak_ordering);
81 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const D&>, std::weak_ordering);
82 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const D&&>, std::weak_ordering);
83 
84 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D, D>, std::weak_ordering);
85 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D&, D&>, std::weak_ordering);
86 ASSERT_SAME_TYPE(std::compare_three_way_result_t<D&&, D&&>, std::weak_ordering);
87 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const D&, const D&>, std::weak_ordering);
88 ASSERT_SAME_TYPE(std::compare_three_way_result_t<const D&&, const D&&>, std::weak_ordering);
89