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_COMMON_COMPARISON_CATEGORY_H
10 #define _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H
11 
12 #include <__compare/ordering.h>
13 #include <__config>
14 #include <__type_traits/is_same.h>
15 #include <cstddef>
16 
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #  pragma GCC system_header
19 #endif
20 
21 _LIBCPP_BEGIN_NAMESPACE_STD
22 
23 #if _LIBCPP_STD_VER >= 20
24 
25 namespace __comp_detail {
26 
27 enum _ClassifyCompCategory : unsigned {
28   _None,
29   _PartialOrd,
30   _WeakOrd,
31   _StrongOrd,
32   _CCC_Size
33 };
34 
35 template <class _Tp>
36 _LIBCPP_HIDE_FROM_ABI
37 constexpr _ClassifyCompCategory __type_to_enum() noexcept {
38   if (is_same_v<_Tp, partial_ordering>)
39     return _PartialOrd;
40   if (is_same_v<_Tp, weak_ordering>)
41     return _WeakOrd;
42   if (is_same_v<_Tp, strong_ordering>)
43     return _StrongOrd;
44   return _None;
45 }
46 
47 template <size_t _Size>
48 _LIBCPP_HIDE_FROM_ABI
49 constexpr _ClassifyCompCategory
50 __compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) {
51   int __seen[_CCC_Size] = {};
52   for (auto __type : __types)
53     ++__seen[__type];
54   if (__seen[_None])
55     return _None;
56   if (__seen[_PartialOrd])
57     return _PartialOrd;
58   if (__seen[_WeakOrd])
59     return _WeakOrd;
60   return _StrongOrd;
61 }
62 
63 template <class ..._Ts, bool _False = false>
64 _LIBCPP_HIDE_FROM_ABI
65 constexpr auto __get_comp_type() {
66   using _CCC = _ClassifyCompCategory;
67   constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...};
68   constexpr _CCC __cat = __comp_detail::__compute_comp_type(__type_kinds);
69   if constexpr (__cat == _None)
70     return void();
71   else if constexpr (__cat == _PartialOrd)
72     return partial_ordering::equivalent;
73   else if constexpr (__cat == _WeakOrd)
74     return weak_ordering::equivalent;
75   else if constexpr (__cat == _StrongOrd)
76     return strong_ordering::equivalent;
77   else
78     static_assert(_False, "unhandled case");
79 }
80 } // namespace __comp_detail
81 
82 // [cmp.common], common comparison category type
83 template<class... _Ts>
84 struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
85   using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
86 };
87 
88 template<class... _Ts>
89 using common_comparison_category_t = typename common_comparison_category<_Ts...>::type;
90 
91 #endif // _LIBCPP_STD_VER >= 20
92 
93 _LIBCPP_END_NAMESPACE_STD
94 
95 #endif // _LIBCPP___COMPARE_COMMON_COMPARISON_CATEGORY_H
96