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