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