]>
Commit | Line | Data |
---|---|---|
b7689b96 JM |
1 | // -*- C++ -*- operator<=> three-way comparison support. |
2 | ||
3 | // Copyright (C) 2019 Free Software Foundation, Inc. | |
4 | // | |
5 | // This file is part of GCC. | |
6 | // | |
7 | // GCC is free software; you can redistribute it and/or modify | |
8 | // it under the terms of the GNU General Public License as published by | |
9 | // the Free Software Foundation; either version 3, or (at your option) | |
10 | // any later version. | |
11 | // | |
12 | // GCC is distributed in the hope that it will be useful, | |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | // GNU General Public License for more details. | |
16 | // | |
17 | // Under Section 7 of GPL version 3, you are granted additional | |
18 | // permissions described in the GCC Runtime Library Exception, version | |
19 | // 3.1, as published by the Free Software Foundation. | |
20 | ||
21 | // You should have received a copy of the GNU General Public License and | |
22 | // a copy of the GCC Runtime Library Exception along with this program; | |
23 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
24 | // <http://www.gnu.org/licenses/>. | |
25 | ||
26 | /** @file compare | |
27 | * This is a Standard C++ Library header. | |
28 | */ | |
29 | ||
30 | #ifndef _COMPARE | |
31 | #define _COMPARE | |
32 | ||
33 | #pragma GCC system_header | |
34 | ||
35 | #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L | |
36 | ||
37 | #pragma GCC visibility push(default) | |
38 | ||
39 | #include <concepts> | |
40 | ||
41 | namespace std | |
42 | { | |
43 | #define __cpp_lib_three_way_comparison 201711L | |
44 | ||
45 | // [cmp.categories], comparison category types | |
46 | ||
47 | namespace __cmp_cat | |
48 | { | |
49 | enum class _Eq | |
50 | { equal = 0, equivalent = equal, nonequal = 1, nonequivalent = nonequal }; | |
51 | ||
52 | enum class _Ord { _Less = -1, _Greater = 1 }; | |
53 | ||
54 | enum class _Ncmp { _Unordered = -127 }; | |
55 | ||
56 | struct __unspec | |
57 | { | |
58 | constexpr __unspec(__unspec*) { } | |
59 | }; | |
60 | } | |
61 | ||
62 | class weak_equality | |
63 | { | |
64 | int _M_value; | |
65 | ||
66 | constexpr explicit | |
67 | weak_equality(__cmp_cat::_Eq __val) noexcept | |
68 | : _M_value(int(__val)) | |
69 | { } | |
70 | ||
71 | public: | |
72 | // valid values | |
73 | ||
74 | static const weak_equality equivalent; | |
75 | static const weak_equality nonequivalent; | |
76 | ||
77 | // comparisons | |
78 | ||
79 | friend constexpr bool | |
80 | operator==(weak_equality __v, __cmp_cat::__unspec) noexcept | |
81 | { return __v._M_value == 0; } | |
82 | ||
83 | friend constexpr bool | |
84 | operator==(weak_equality, weak_equality) noexcept = default; | |
85 | ||
86 | friend constexpr weak_equality | |
87 | operator<=>(weak_equality __v, __cmp_cat::__unspec) noexcept | |
88 | { return __v; } | |
89 | ||
90 | friend constexpr weak_equality | |
91 | operator<=>(__cmp_cat::__unspec, weak_equality __v) noexcept | |
92 | { return __v; } | |
93 | }; | |
94 | ||
95 | // valid values' definitions | |
96 | inline constexpr weak_equality | |
97 | weak_equality::equivalent(__cmp_cat::_Eq::equivalent); | |
98 | ||
99 | inline constexpr weak_equality | |
100 | weak_equality::nonequivalent(__cmp_cat::_Eq::nonequivalent); | |
101 | ||
102 | class strong_equality | |
103 | { | |
104 | int _M_value; | |
105 | ||
106 | constexpr explicit | |
107 | strong_equality(__cmp_cat::_Eq __val) noexcept | |
108 | : _M_value(int(__val)) | |
109 | { } | |
110 | ||
111 | public: | |
112 | // valid values | |
113 | ||
114 | static const strong_equality equal; | |
115 | static const strong_equality nonequal; | |
116 | static const strong_equality equivalent; | |
117 | static const strong_equality nonequivalent; | |
118 | ||
119 | // conversion | |
120 | constexpr operator weak_equality() const noexcept | |
121 | { | |
122 | if (_M_value == 0) | |
123 | return weak_equality::equivalent; | |
124 | else | |
125 | return weak_equality::nonequivalent; | |
126 | } | |
127 | ||
128 | // comparisons | |
129 | ||
130 | friend constexpr bool | |
131 | operator==(strong_equality __v, __cmp_cat::__unspec) noexcept | |
132 | { return __v._M_value == 0; } | |
133 | ||
134 | friend constexpr bool | |
135 | operator==(strong_equality, strong_equality) noexcept = default; | |
136 | ||
137 | friend constexpr strong_equality | |
138 | operator<=>(strong_equality __v, __cmp_cat::__unspec) noexcept | |
139 | { return __v; } | |
140 | ||
141 | friend constexpr strong_equality | |
142 | operator<=>(__cmp_cat::__unspec, strong_equality __v) noexcept | |
143 | { return __v; } | |
144 | }; | |
145 | ||
146 | // valid values' definitions | |
147 | inline constexpr strong_equality | |
148 | strong_equality::equal(__cmp_cat::_Eq::equal); | |
149 | ||
150 | inline constexpr strong_equality | |
151 | strong_equality::nonequal(__cmp_cat::_Eq::nonequal); | |
152 | ||
153 | inline constexpr strong_equality | |
154 | strong_equality::equivalent(__cmp_cat::_Eq::equivalent); | |
155 | ||
156 | inline constexpr strong_equality | |
157 | strong_equality::nonequivalent(__cmp_cat::_Eq::nonequivalent); | |
158 | ||
159 | class partial_ordering | |
160 | { | |
161 | int _M_value; | |
162 | bool _M_is_ordered; | |
163 | ||
164 | constexpr explicit | |
165 | partial_ordering(__cmp_cat::_Eq __v) noexcept | |
166 | : _M_value(int(__v)), _M_is_ordered(true) | |
167 | { } | |
168 | ||
169 | constexpr explicit | |
170 | partial_ordering(__cmp_cat::_Ord __v) noexcept | |
171 | : _M_value(int(__v)), _M_is_ordered(true) | |
172 | { } | |
173 | ||
174 | constexpr explicit | |
175 | partial_ordering(__cmp_cat::_Ncmp __v) noexcept | |
176 | : _M_value(int(__v)), _M_is_ordered(false) | |
177 | { } | |
178 | ||
179 | public: | |
180 | // valid values | |
181 | static const partial_ordering less; | |
182 | static const partial_ordering equivalent; | |
183 | static const partial_ordering greater; | |
184 | static const partial_ordering unordered; | |
185 | ||
186 | // conversion | |
187 | constexpr operator weak_equality() const noexcept | |
188 | { | |
189 | if (_M_value == 0) | |
190 | return weak_equality::equivalent; | |
191 | else | |
192 | return weak_equality::nonequivalent; | |
193 | } | |
194 | ||
195 | // comparisons | |
196 | friend constexpr bool | |
197 | operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept | |
198 | { return __v._M_is_ordered && __v._M_value == 0; } | |
199 | ||
200 | friend constexpr bool | |
201 | operator==(partial_ordering, partial_ordering) noexcept = default; | |
202 | ||
203 | friend constexpr bool | |
204 | operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept | |
205 | { return __v._M_is_ordered && __v._M_value < 0; } | |
206 | ||
207 | friend constexpr bool | |
208 | operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept | |
209 | { return __v._M_is_ordered && __v._M_value > 0; } | |
210 | ||
211 | friend constexpr bool | |
212 | operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept | |
213 | { return __v._M_is_ordered && __v._M_value <= 0; } | |
214 | ||
215 | friend constexpr bool | |
216 | operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept | |
217 | { return __v._M_is_ordered && __v._M_value >= 0; } | |
218 | ||
219 | friend constexpr bool | |
220 | operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept | |
221 | { return __v._M_is_ordered && 0 < __v._M_value; } | |
222 | ||
223 | friend constexpr bool | |
224 | operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept | |
225 | { return __v._M_is_ordered && 0 > __v._M_value; } | |
226 | ||
227 | friend constexpr bool | |
228 | operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept | |
229 | { return __v._M_is_ordered && 0 <= __v._M_value; } | |
230 | ||
231 | friend constexpr bool | |
232 | operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept | |
233 | { return __v._M_is_ordered && 0 >= __v._M_value; } | |
234 | ||
235 | friend constexpr partial_ordering | |
236 | operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept | |
237 | { return __v; } | |
238 | ||
239 | friend constexpr partial_ordering | |
240 | operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept | |
241 | { | |
242 | if (__v < 0) | |
243 | return partial_ordering::greater; | |
244 | else if (__v > 0) | |
245 | return partial_ordering::less; | |
246 | else | |
247 | return __v; | |
248 | } | |
249 | }; | |
250 | ||
251 | // valid values' definitions | |
252 | inline constexpr partial_ordering | |
253 | partial_ordering::less(__cmp_cat::_Ord::_Less); | |
254 | ||
255 | inline constexpr partial_ordering | |
256 | partial_ordering::equivalent(__cmp_cat::_Eq::equivalent); | |
257 | ||
258 | inline constexpr partial_ordering | |
259 | partial_ordering::greater(__cmp_cat::_Ord::_Greater); | |
260 | ||
261 | inline constexpr partial_ordering | |
262 | partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered); | |
263 | ||
264 | class weak_ordering | |
265 | { | |
266 | int _M_value; | |
267 | ||
268 | constexpr explicit | |
269 | weak_ordering(__cmp_cat::_Eq __v) noexcept : _M_value(int(__v)) | |
270 | { } | |
271 | ||
272 | constexpr explicit | |
273 | weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(int(__v)) | |
274 | { } | |
275 | ||
276 | public: | |
277 | // valid values | |
278 | static const weak_ordering less; | |
279 | static const weak_ordering equivalent; | |
280 | static const weak_ordering greater; | |
281 | ||
282 | // conversions | |
283 | constexpr operator weak_equality() const noexcept | |
284 | { | |
285 | if (_M_value == 0) | |
286 | return weak_equality::equivalent; | |
287 | else | |
288 | return weak_equality::nonequivalent; | |
289 | } | |
290 | ||
291 | constexpr operator partial_ordering() const noexcept | |
292 | { | |
293 | if (_M_value == 0) | |
294 | return partial_ordering::equivalent; | |
295 | else if (_M_value < 0) | |
296 | return partial_ordering::less; | |
297 | else | |
298 | return partial_ordering::greater; | |
299 | } | |
300 | ||
301 | // comparisons | |
302 | friend constexpr bool | |
303 | operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept | |
304 | { return __v._M_value == 0; } | |
305 | ||
306 | friend constexpr bool | |
307 | operator==(weak_ordering, weak_ordering) noexcept = default; | |
308 | ||
309 | friend constexpr bool | |
310 | operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept | |
311 | { return __v._M_value < 0; } | |
312 | ||
313 | friend constexpr bool | |
314 | operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept | |
315 | { return __v._M_value > 0; } | |
316 | ||
317 | friend constexpr bool | |
318 | operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept | |
319 | { return __v._M_value <= 0; } | |
320 | ||
321 | friend constexpr bool | |
322 | operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept | |
323 | { return __v._M_value >= 0; } | |
324 | ||
325 | friend constexpr bool | |
326 | operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept | |
327 | { return 0 < __v._M_value; } | |
328 | ||
329 | friend constexpr bool | |
330 | operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept | |
331 | { return 0 > __v._M_value; } | |
332 | ||
333 | friend constexpr bool | |
334 | operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept | |
335 | { return 0 <= __v._M_value; } | |
336 | ||
337 | friend constexpr bool | |
338 | operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept | |
339 | { return 0 >= __v._M_value; } | |
340 | ||
341 | friend constexpr weak_ordering | |
342 | operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept | |
343 | { return __v; } | |
344 | ||
345 | friend constexpr weak_ordering | |
346 | operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept | |
347 | { | |
348 | if (__v < 0) | |
349 | return weak_ordering::greater; | |
350 | else if (__v > 0) | |
351 | return weak_ordering::less; | |
352 | else | |
353 | return __v; | |
354 | } | |
355 | }; | |
356 | ||
357 | // valid values' definitions | |
358 | inline constexpr weak_ordering | |
359 | weak_ordering::less(__cmp_cat::_Ord::_Less); | |
360 | ||
361 | inline constexpr weak_ordering | |
362 | weak_ordering::equivalent(__cmp_cat::_Eq::equivalent); | |
363 | ||
364 | inline constexpr weak_ordering | |
365 | weak_ordering::greater(__cmp_cat::_Ord::_Greater); | |
366 | ||
367 | class strong_ordering | |
368 | { | |
369 | int _M_value; | |
370 | ||
371 | constexpr explicit | |
372 | strong_ordering(__cmp_cat::_Eq __v) noexcept | |
373 | : _M_value(int(__v)) | |
374 | { } | |
375 | ||
376 | constexpr explicit | |
377 | strong_ordering(__cmp_cat::_Ord __v) noexcept | |
378 | : _M_value(int(__v)) | |
379 | { } | |
380 | ||
381 | public: | |
382 | // valid values | |
383 | static const strong_ordering less; | |
384 | static const strong_ordering equal; | |
385 | static const strong_ordering equivalent; | |
386 | static const strong_ordering greater; | |
387 | ||
388 | // conversions | |
389 | constexpr operator weak_equality() const noexcept | |
390 | { | |
391 | if (_M_value == 0) | |
392 | return weak_equality::equivalent; | |
393 | else | |
394 | return weak_equality::nonequivalent; | |
395 | } | |
396 | ||
397 | constexpr operator strong_equality() const noexcept | |
398 | { | |
399 | if (_M_value == 0) | |
400 | return strong_equality::equal; | |
401 | else | |
402 | return strong_equality::nonequal; | |
403 | } | |
404 | ||
405 | constexpr operator partial_ordering() const noexcept | |
406 | { | |
407 | if (_M_value == 0) | |
408 | return partial_ordering::equivalent; | |
409 | else if (_M_value < 0) | |
410 | return partial_ordering::less; | |
411 | else | |
412 | return partial_ordering::greater; | |
413 | } | |
414 | ||
415 | constexpr operator weak_ordering() const noexcept | |
416 | { | |
417 | if (_M_value == 0) | |
418 | return weak_ordering::equivalent; | |
419 | else if (_M_value < 0) | |
420 | return weak_ordering::less; | |
421 | else | |
422 | return weak_ordering::greater; | |
423 | } | |
424 | ||
425 | // comparisons | |
426 | friend constexpr bool | |
427 | operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept | |
428 | { return __v._M_value == 0; } | |
429 | ||
430 | friend constexpr bool | |
431 | operator==(strong_ordering, strong_ordering) noexcept = default; | |
432 | ||
433 | friend constexpr bool | |
434 | operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept | |
435 | { return __v._M_value < 0; } | |
436 | ||
437 | friend constexpr bool | |
438 | operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept | |
439 | { return __v._M_value > 0; } | |
440 | ||
441 | friend constexpr bool | |
442 | operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept | |
443 | { return __v._M_value <= 0; } | |
444 | ||
445 | friend constexpr bool | |
446 | operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept | |
447 | { return __v._M_value >= 0; } | |
448 | ||
449 | friend constexpr bool | |
450 | operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept | |
451 | { return 0 < __v._M_value; } | |
452 | ||
453 | friend constexpr bool | |
454 | operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept | |
455 | { return 0 > __v._M_value; } | |
456 | ||
457 | friend constexpr bool | |
458 | operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept | |
459 | { return 0 <= __v._M_value; } | |
460 | ||
461 | friend constexpr bool | |
462 | operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept | |
463 | { return 0 >= __v._M_value; } | |
464 | ||
465 | friend constexpr strong_ordering | |
466 | operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept | |
467 | { return __v; } | |
468 | ||
469 | friend constexpr strong_ordering | |
470 | operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept | |
471 | { | |
472 | if (__v < 0) | |
473 | return strong_ordering::greater; | |
474 | else if (__v > 0) | |
475 | return strong_ordering::less; | |
476 | else | |
477 | return __v; | |
478 | } | |
479 | }; | |
480 | ||
481 | // valid values' definitions | |
482 | inline constexpr strong_ordering | |
483 | strong_ordering::less(__cmp_cat::_Ord::_Less); | |
484 | ||
485 | inline constexpr strong_ordering | |
486 | strong_ordering::equal(__cmp_cat::_Eq::equal); | |
487 | ||
488 | inline constexpr strong_ordering | |
489 | strong_ordering::equivalent(__cmp_cat::_Eq::equivalent); | |
490 | ||
491 | inline constexpr strong_ordering | |
492 | strong_ordering::greater(__cmp_cat::_Ord::_Greater); | |
493 | ||
494 | ||
495 | // named comparison functions | |
496 | constexpr bool | |
497 | is_eq(weak_equality __cmp) noexcept | |
498 | { return __cmp == 0; } | |
499 | ||
500 | constexpr bool | |
501 | is_neq(weak_equality __cmp) noexcept | |
502 | { return __cmp != 0; } | |
503 | ||
504 | constexpr bool | |
505 | is_lt (partial_ordering __cmp) noexcept | |
506 | { return __cmp < 0; } | |
507 | ||
508 | constexpr bool | |
509 | is_lteq(partial_ordering __cmp) noexcept | |
510 | { return __cmp <= 0; } | |
511 | ||
512 | constexpr bool | |
513 | is_gt (partial_ordering __cmp) noexcept | |
514 | { return __cmp > 0; } | |
515 | ||
516 | constexpr bool | |
517 | is_gteq(partial_ordering __cmp) noexcept | |
518 | { return __cmp >= 0; } | |
519 | ||
520 | // [cmp.common], common comparison category type | |
521 | template<typename... _Ts> | |
522 | struct common_comparison_category { | |
523 | // using type = TODO | |
524 | }; | |
525 | ||
526 | template<typename... _Ts> | |
527 | using common_comparison_category_t | |
528 | = typename common_comparison_category<_Ts...>::type; | |
529 | ||
530 | #if __cpp_concepts | |
531 | namespace __detail | |
532 | { | |
533 | template<typename _Tp, typename _Cat> | |
534 | concept __compares_as | |
535 | = same_as<common_comparison_category_t<_Tp, _Cat>, _Cat>; | |
536 | ||
537 | template<typename _Tp, typename _Up> | |
538 | concept __partially_ordered_with | |
539 | = requires(const remove_reference_t<_Tp>& __t, | |
540 | const remove_reference_t<_Up>& __u) { | |
541 | { __t < __u } -> boolean; | |
542 | { __t > __u } -> boolean; | |
543 | { __t <= __u } -> boolean; | |
544 | { __t >= __u } -> boolean; | |
545 | { __u < __t } -> boolean; | |
546 | { __u > __t } -> boolean; | |
547 | { __u <= __t } -> boolean; | |
548 | { __u >= __t } -> boolean; | |
549 | }; | |
550 | } // namespace __detail | |
551 | ||
552 | // [cmp.concept], concept three_way_comparable | |
553 | template<typename _Tp, typename _Cat = partial_ordering> | |
554 | concept three_way_comparable | |
555 | = __detail::__weakly_eq_cmp_with<_Tp, _Tp> | |
556 | && (!convertible_to<_Cat, partial_ordering> | |
557 | || __detail::__partially_ordered_with<_Tp, _Tp>) | |
558 | && requires(const remove_reference_t<_Tp>& __a, | |
559 | const remove_reference_t<_Tp>& __b) { | |
560 | { __a <=> __b } -> __detail::__compares_as<_Cat>; | |
561 | }; | |
562 | ||
563 | template<typename _Tp, typename _Up, typename _Cat = partial_ordering> | |
564 | concept three_way_comparable_with | |
565 | = __detail::__weakly_eq_cmp_with<_Tp, _Up> | |
566 | && (!convertible_to<_Cat, partial_ordering> | |
567 | || __detail::__partially_ordered_with<_Tp, _Up>) | |
568 | && three_way_comparable<_Tp, _Cat> | |
569 | && three_way_comparable<_Up, _Cat> | |
570 | && common_reference_with<const remove_reference_t<_Tp>&, | |
571 | const remove_reference_t<_Up>&> | |
572 | && three_way_comparable< | |
573 | common_reference_t<const remove_reference_t<_Tp>&, | |
574 | const remove_reference_t<_Up>&>, _Cat> | |
575 | && requires(const remove_reference_t<_Tp>& __t, | |
576 | const remove_reference_t<_Up>& __u) { | |
577 | { __t <=> __u } -> __detail::__compares_as<_Cat>; | |
578 | { __u <=> __t } -> __detail::__compares_as<_Cat>; | |
579 | }; | |
580 | #endif | |
581 | ||
582 | template<typename _Tp, typename _Up> | |
583 | using __cmp2way_res_t | |
584 | = decltype(std::declval<_Tp&>() <=> std::declval<_Up&>()); | |
585 | ||
586 | template<typename _Tp, typename _Up = _Tp, typename = void> | |
587 | struct __cmp3way_helper | |
588 | { }; | |
589 | ||
590 | template<typename _Tp, typename _Up> | |
591 | struct __cmp3way_helper<_Tp, _Up, void_t<__cmp2way_res_t<_Tp, _Up>>> | |
592 | { | |
593 | using type = __cmp2way_res_t<_Tp, _Up>; | |
594 | using __type = type; | |
595 | }; | |
596 | ||
597 | /// [cmp.result], result of three-way comparison | |
598 | template<typename _Tp, typename _Up = _Tp> | |
599 | struct compare_three_way_result | |
600 | : __cmp3way_helper<_Tp, _Up> | |
601 | { }; | |
602 | ||
603 | template<typename _Tp, typename _Up = _Tp> | |
604 | using compare_three_way_result_t | |
605 | = typename compare_three_way_result<_Tp, _Up>::__type; | |
606 | ||
607 | // [cmp.object], typename compare_three_way | |
608 | struct compare_three_way | |
609 | { | |
610 | // TODO | |
611 | #if 0 | |
612 | template<typename _Tp, typename _Up> | |
613 | requires (three_way_comparable_with<_Tp, _Up> | |
614 | || BUILTIN-PTR-THREE-WAY(_Tp, _Up)) | |
615 | constexpr auto | |
616 | operator()(_Tp&& __t, _Up&& __u) const noexcept | |
617 | { | |
618 | // TODO | |
619 | } | |
620 | #endif | |
621 | ||
622 | using is_transparent = void; | |
623 | }; | |
624 | ||
625 | // [cmp.alg], comparison algorithms | |
626 | inline namespace __cmp_alg | |
627 | { | |
628 | // TODO | |
629 | #if 0 | |
630 | inline constexpr unspecified strong_order = unspecified; | |
631 | inline constexpr unspecified weak_order = unspecified; | |
632 | inline constexpr unspecified partial_order = unspecified; | |
633 | inline constexpr unspecified compare_strong_order_fallback = unspecified; | |
634 | inline constexpr unspecified compare_weak_order_fallback = unspecified; | |
635 | inline constexpr unspecified compare_partial_order_fallback = unspecified; | |
636 | #endif | |
637 | } | |
638 | } | |
639 | ||
640 | #pragma GCC visibility pop | |
641 | ||
642 | #endif // C++20 | |
643 | ||
644 | #endif // _COMPARE |