master
 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 <__cstddef/size_t.h>
15#include <__type_traits/is_same.h>
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
25namespace __comp_detail {
26
27enum _ClassifyCompCategory : unsigned { _None, _PartialOrd, _WeakOrd, _StrongOrd, _CCC_Size };
28
29template <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
40template <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
55template <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, __comp_detail::__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
74template <class... _Ts>
75struct common_comparison_category {
76  using type _LIBCPP_NODEBUG = decltype(__comp_detail::__get_comp_type<_Ts...>());
77};
78
79template <class... _Ts>
80using 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