xref: /llvm-project/libcxx/include/__compare/ordering.h (revision f69585235ec85d54e0f3fc41b2d5700430907f99)
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 #ifndef _LIBCPP___COMPARE_ORDERING_H
10 #define _LIBCPP___COMPARE_ORDERING_H
11 
12 #include <__config>
13 #include <__type_traits/enable_if.h>
14 #include <__type_traits/is_same.h>
15 
16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17 #  pragma GCC system_header
18 #endif
19 
20 _LIBCPP_BEGIN_NAMESPACE_STD
21 
22 #if _LIBCPP_STD_VER >= 20
23 
24 // exposition only
25 enum class _OrdResult : signed char { __less = -1, __equiv = 0, __greater = 1 };
26 
27 enum class _PartialOrdResult : signed char {
28   __less      = static_cast<signed char>(_OrdResult::__less),
29   __equiv     = static_cast<signed char>(_OrdResult::__equiv),
30   __greater   = static_cast<signed char>(_OrdResult::__greater),
31   __unordered = -127,
32 };
33 
34 class partial_ordering;
35 class weak_ordering;
36 class strong_ordering;
37 
38 struct _CmpUnspecifiedParam {
39   // If anything other than a literal 0 is provided, the behavior is undefined by the Standard.
40   //
41   // The alternative to the `__enable_if__` attribute would be to use the fact that a pointer
42   // can be constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
43   template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int> > >
44   _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept
45 #  if __has_attribute(__enable_if__)
46       __attribute__((__enable_if__(
47           __zero == 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types")))
48 #  endif
49   {
50     (void)__zero;
51   }
52 };
53 
54 class partial_ordering {
55   _LIBCPP_HIDE_FROM_ABI explicit constexpr partial_ordering(_PartialOrdResult __v) noexcept : __value_(__v) {}
56 
57 public:
58   // valid values
59   static const partial_ordering less;
60   static const partial_ordering equivalent;
61   static const partial_ordering greater;
62   static const partial_ordering unordered;
63 
64   // comparisons
65   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
66 
67   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
68     return __v.__value_ == _PartialOrdResult::__equiv;
69   }
70 
71   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
72     return __v.__value_ == _PartialOrdResult::__less;
73   }
74 
75   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
76     return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;
77   }
78 
79   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
80     return __v.__value_ == _PartialOrdResult::__greater;
81   }
82 
83   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
84     return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;
85   }
86 
87   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
88     return __v.__value_ == _PartialOrdResult::__greater;
89   }
90 
91   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
92     return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;
93   }
94 
95   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
96     return __v.__value_ == _PartialOrdResult::__less;
97   }
98 
99   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
100     return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;
101   }
102 
103   _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering
104   operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
105     return __v;
106   }
107 
108   _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering
109   operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
110     return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
111   }
112 
113 private:
114   _PartialOrdResult __value_;
115 };
116 
117 inline constexpr partial_ordering partial_ordering::less(_PartialOrdResult::__less);
118 inline constexpr partial_ordering partial_ordering::equivalent(_PartialOrdResult::__equiv);
119 inline constexpr partial_ordering partial_ordering::greater(_PartialOrdResult::__greater);
120 inline constexpr partial_ordering partial_ordering::unordered(_PartialOrdResult::__unordered);
121 
122 class weak_ordering {
123   using _ValueT _LIBCPP_NODEBUG = signed char;
124 
125   _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
126 
127 public:
128   static const weak_ordering less;
129   static const weak_ordering equivalent;
130   static const weak_ordering greater;
131 
132   _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {
133     return __value_ == 0 ? partial_ordering::equivalent
134                          : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
135   }
136 
137   // comparisons
138   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
139 
140   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
141     return __v.__value_ == 0;
142   }
143 
144   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
145     return __v.__value_ < 0;
146   }
147 
148   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
149     return __v.__value_ <= 0;
150   }
151 
152   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
153     return __v.__value_ > 0;
154   }
155 
156   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
157     return __v.__value_ >= 0;
158   }
159 
160   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
161     return 0 < __v.__value_;
162   }
163 
164   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
165     return 0 <= __v.__value_;
166   }
167 
168   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
169     return 0 > __v.__value_;
170   }
171 
172   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
173     return 0 >= __v.__value_;
174   }
175 
176   _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
177     return __v;
178   }
179 
180   _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
181     return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
182   }
183 
184 private:
185   _ValueT __value_;
186 };
187 
188 inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
189 inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv);
190 inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
191 
192 class strong_ordering {
193   using _ValueT _LIBCPP_NODEBUG = signed char;
194 
195   _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
196 
197 public:
198   static const strong_ordering less;
199   static const strong_ordering equal;
200   static const strong_ordering equivalent;
201   static const strong_ordering greater;
202 
203   // conversions
204   _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {
205     return __value_ == 0 ? partial_ordering::equivalent
206                          : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
207   }
208 
209   _LIBCPP_HIDE_FROM_ABI constexpr operator weak_ordering() const noexcept {
210     return __value_ == 0 ? weak_ordering::equivalent : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
211   }
212 
213   // comparisons
214   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
215 
216   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
217     return __v.__value_ == 0;
218   }
219 
220   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
221     return __v.__value_ < 0;
222   }
223 
224   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
225     return __v.__value_ <= 0;
226   }
227 
228   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
229     return __v.__value_ > 0;
230   }
231 
232   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
233     return __v.__value_ >= 0;
234   }
235 
236   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
237     return 0 < __v.__value_;
238   }
239 
240   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
241     return 0 <= __v.__value_;
242   }
243 
244   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
245     return 0 > __v.__value_;
246   }
247 
248   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
249     return 0 >= __v.__value_;
250   }
251 
252   _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering
253   operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
254     return __v;
255   }
256 
257   _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering
258   operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
259     return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
260   }
261 
262 private:
263   _ValueT __value_;
264 };
265 
266 inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
267 inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);
268 inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);
269 inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
270 
271 /// [cmp.categories.pre]/1
272 /// The types partial_ordering, weak_ordering, and strong_ordering are
273 /// collectively termed the comparison category types.
274 template <class _Tp>
275 concept __comparison_category =
276     is_same_v<_Tp, partial_ordering> || is_same_v<_Tp, weak_ordering> || is_same_v<_Tp, strong_ordering>;
277 
278 #endif // _LIBCPP_STD_VER >= 20
279 
280 _LIBCPP_END_NAMESPACE_STD
281 
282 #endif // _LIBCPP___COMPARE_ORDERING_H
283