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