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 // UNSUPPORTED: libcpp-no-concepts
11 
12 // template<class T>
13 // concept totally_ordered;
14 
15 #include <concepts>
16 
17 #include <array>
18 #include <deque>
19 #include <forward_list>
20 #include <list>
21 #include <map>
22 #include <memory>
23 #include <optional>
24 #include <set>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include <vector>
28 
29 #include "compare_types.h"
30 #include "test_macros.h"
31 
32 // `models_totally_ordered` checks that `std::totally_ordered` subsumes
33 // `std::equality_comparable`. This overload should *never* be called.
34 template <std::equality_comparable T>
35 constexpr bool models_totally_ordered() noexcept {
36   return false;
37 }
38 
39 template <std::totally_ordered T>
40 constexpr bool models_totally_ordered() noexcept {
41   return true;
42 }
43 
44 namespace fundamentals {
45 static_assert(models_totally_ordered<int>());
46 static_assert(models_totally_ordered<double>());
47 static_assert(models_totally_ordered<void*>());
48 static_assert(models_totally_ordered<char*>());
49 static_assert(models_totally_ordered<char const*>());
50 static_assert(models_totally_ordered<char volatile*>());
51 static_assert(models_totally_ordered<char const volatile*>());
52 static_assert(models_totally_ordered<wchar_t&>());
53 static_assert(models_totally_ordered<char8_t const&>());
54 static_assert(models_totally_ordered<char16_t volatile&>());
55 static_assert(models_totally_ordered<char32_t const volatile&>());
56 static_assert(models_totally_ordered<unsigned char&&>());
57 static_assert(models_totally_ordered<unsigned short const&&>());
58 static_assert(models_totally_ordered<unsigned int volatile&&>());
59 static_assert(models_totally_ordered<unsigned long const volatile&&>());
60 static_assert(models_totally_ordered<int[5]>());
61 static_assert(models_totally_ordered<int (*)(int)>());
62 static_assert(models_totally_ordered<int (&)(int)>());
63 static_assert(models_totally_ordered<int (*)(int) noexcept>());
64 static_assert(models_totally_ordered<int (&)(int) noexcept>());
65 
66 #ifndef TEST_COMPILER_GCC
67 static_assert(!std::totally_ordered<std::nullptr_t>);
68 #endif
69 
70 struct S {};
71 static_assert(!std::totally_ordered<S>);
72 static_assert(!std::totally_ordered<int S::*>);
73 static_assert(!std::totally_ordered<int (S::*)()>);
74 static_assert(!std::totally_ordered<int (S::*)() noexcept>);
75 static_assert(!std::totally_ordered<int (S::*)() &>);
76 static_assert(!std::totally_ordered<int (S::*)() & noexcept>);
77 static_assert(!std::totally_ordered<int (S::*)() &&>);
78 static_assert(!std::totally_ordered < int (S::*)() && noexcept >);
79 static_assert(!std::totally_ordered<int (S::*)() const>);
80 static_assert(!std::totally_ordered<int (S::*)() const noexcept>);
81 static_assert(!std::totally_ordered<int (S::*)() const&>);
82 static_assert(!std::totally_ordered<int (S::*)() const & noexcept>);
83 static_assert(!std::totally_ordered<int (S::*)() const&&>);
84 static_assert(!std::totally_ordered < int (S::*)() const&& noexcept >);
85 static_assert(!std::totally_ordered<int (S::*)() volatile>);
86 static_assert(!std::totally_ordered<int (S::*)() volatile noexcept>);
87 static_assert(!std::totally_ordered<int (S::*)() volatile&>);
88 static_assert(!std::totally_ordered<int (S::*)() volatile & noexcept>);
89 static_assert(!std::totally_ordered<int (S::*)() volatile&&>);
90 static_assert(!std::totally_ordered < int (S::*)() volatile&& noexcept >);
91 static_assert(!std::totally_ordered<int (S::*)() const volatile>);
92 static_assert(!std::totally_ordered<int (S::*)() const volatile noexcept>);
93 static_assert(!std::totally_ordered<int (S::*)() const volatile&>);
94 static_assert(!std::totally_ordered<int (S::*)() const volatile & noexcept>);
95 static_assert(!std::totally_ordered<int (S::*)() const volatile&&>);
96 static_assert(!std::totally_ordered < int (S::*)() const volatile&& noexcept >);
97 
98 static_assert(!std::totally_ordered<void>);
99 } // namespace fundamentals
100 
101 namespace standard_types {
102 static_assert(models_totally_ordered<std::array<int, 10> >());
103 static_assert(models_totally_ordered<std::deque<int> >());
104 static_assert(models_totally_ordered<std::forward_list<int> >());
105 static_assert(models_totally_ordered<std::list<int> >());
106 static_assert(models_totally_ordered<std::optional<int> >());
107 static_assert(models_totally_ordered<std::set<int> >());
108 static_assert(models_totally_ordered<std::vector<bool> >());
109 static_assert(models_totally_ordered<std::vector<int> >());
110 
111 static_assert(!std::totally_ordered<std::unordered_map<int, void*> >);
112 static_assert(!std::totally_ordered<std::unordered_set<int> >);
113 
114 struct A {};
115 // FIXME(cjdb): uncomment when operator<=> is implemented for each of these types.
116 // static_assert(!std::totally_ordered<std::array<A, 10> >);
117 // static_assert(!std::totally_ordered<std::deque<A> >);
118 // static_assert(!std::totally_ordered<std::forward_list<A> >);
119 // static_assert(!std::totally_ordered<std::list<A> >);
120 static_assert(!std::totally_ordered<std::optional<A> >);
121 // static_assert(!std::totally_ordered<std::set<A> >);
122 // static_assert(!std::totally_ordered<std::vector<A> >);
123 } // namespace standard_types
124 
125 namespace types_fit_for_purpose {
126 static_assert(models_totally_ordered<member_three_way_comparable>());
127 static_assert(models_totally_ordered<friend_three_way_comparable>());
128 static_assert(models_totally_ordered<explicit_operators>());
129 static_assert(models_totally_ordered<different_return_types>());
130 static_assert(!std::totally_ordered<cxx20_member_eq>);
131 static_assert(!std::totally_ordered<cxx20_friend_eq>);
132 static_assert(!std::totally_ordered<one_member_one_friend>);
133 static_assert(!std::totally_ordered<equality_comparable_with_ec1>);
134 
135 static_assert(!std::totally_ordered<no_eq>);
136 static_assert(!std::totally_ordered<no_neq>);
137 static_assert(!std::totally_ordered<no_lt>);
138 static_assert(!std::totally_ordered<no_gt>);
139 static_assert(!std::totally_ordered<no_le>);
140 static_assert(!std::totally_ordered<no_ge>);
141 
142 static_assert(!std::totally_ordered<wrong_return_type_eq>);
143 static_assert(!std::totally_ordered<wrong_return_type_ne>);
144 static_assert(!std::totally_ordered<wrong_return_type_lt>);
145 static_assert(!std::totally_ordered<wrong_return_type_gt>);
146 static_assert(!std::totally_ordered<wrong_return_type_le>);
147 static_assert(!std::totally_ordered<wrong_return_type_ge>);
148 static_assert(!std::totally_ordered<wrong_return_type>);
149 
150 static_assert(!std::totally_ordered<cxx20_member_eq_operator_with_deleted_ne>);
151 static_assert(!std::totally_ordered<cxx20_friend_eq_operator_with_deleted_ne>);
152 static_assert(
153     !std::totally_ordered<member_three_way_comparable_with_deleted_eq>);
154 static_assert(
155     !std::totally_ordered<member_three_way_comparable_with_deleted_ne>);
156 static_assert(
157     !std::totally_ordered<friend_three_way_comparable_with_deleted_eq>);
158 static_assert(
159     !std::totally_ordered<friend_three_way_comparable_with_deleted_ne>);
160 
161 static_assert(!std::totally_ordered<eq_returns_explicit_bool>);
162 static_assert(!std::totally_ordered<ne_returns_explicit_bool>);
163 static_assert(!std::totally_ordered<lt_returns_explicit_bool>);
164 static_assert(!std::totally_ordered<gt_returns_explicit_bool>);
165 static_assert(!std::totally_ordered<le_returns_explicit_bool>);
166 static_assert(!std::totally_ordered<ge_returns_explicit_bool>);
167 static_assert(std::totally_ordered<returns_true_type>);
168 static_assert(std::totally_ordered<returns_int_ptr>);
169 
170 static_assert(std::totally_ordered<partial_ordering_totally_ordered_with>);
171 static_assert(std::totally_ordered<weak_ordering_totally_ordered_with>);
172 static_assert(std::totally_ordered<strong_ordering_totally_ordered_with>);
173 } // namespace types_fit_for_purpose
174 
175 int main(int, char**) { return 0; }
176