283 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___COMPARE_ORDERING_H10#define _LIBCPP___COMPARE_ORDERING_H11 12#include <__config>13#include <__type_traits/enable_if.h>14#include <__type_traits/is_same.h>15 16#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)17# pragma GCC system_header18#endif19 20_LIBCPP_BEGIN_NAMESPACE_STD21 22#if _LIBCPP_STD_VER >= 2023 24// exposition only25enum class _OrdResult : signed char { __less = -1, __equiv = 0, __greater = 1 };26 27enum class _PartialOrdResult : signed char {28 __less = static_cast<signed char>(_OrdResult::__less),29 __equiv = static_cast<signed char>(_OrdResult::__equiv),30 __greater = static_cast<signed char>(_OrdResult::__greater),31 __unordered = -127,32};33 34class partial_ordering;35class weak_ordering;36class strong_ordering;37 38struct _CmpUnspecifiedParam {39 // If anything other than a literal 0 is provided, the behavior is undefined by the Standard.40 //41 // The alternative to the `__enable_if__` attribute would be to use the fact that a pointer42 // can be constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.43 template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int> > >44 _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept45# if __has_attribute(__enable_if__)46 __attribute__((__enable_if__(47 __zero == 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types")))48# endif49 {50 (void)__zero;51 }52};53 54class partial_ordering {55 _LIBCPP_HIDE_FROM_ABI explicit constexpr partial_ordering(_PartialOrdResult __v) noexcept : __value_(__v) {}56 57public:58 // valid values59 static const partial_ordering less;60 static const partial_ordering equivalent;61 static const partial_ordering greater;62 static const partial_ordering unordered;63 64 // comparisons65 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;66 67 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {68 return __v.__value_ == _PartialOrdResult::__equiv;69 }70 71 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {72 return __v.__value_ == _PartialOrdResult::__less;73 }74 75 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {76 return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;77 }78 79 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {80 return __v.__value_ == _PartialOrdResult::__greater;81 }82 83 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {84 return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;85 }86 87 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {88 return __v.__value_ == _PartialOrdResult::__greater;89 }90 91 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {92 return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;93 }94 95 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {96 return __v.__value_ == _PartialOrdResult::__less;97 }98 99 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {100 return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;101 }102 103 _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering104 operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {105 return __v;106 }107 108 _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering109 operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {110 return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);111 }112 113private:114 _PartialOrdResult __value_;115};116 117inline constexpr partial_ordering partial_ordering::less(_PartialOrdResult::__less);118inline constexpr partial_ordering partial_ordering::equivalent(_PartialOrdResult::__equiv);119inline constexpr partial_ordering partial_ordering::greater(_PartialOrdResult::__greater);120inline constexpr partial_ordering partial_ordering::unordered(_PartialOrdResult::__unordered);121 122class weak_ordering {123 using _ValueT _LIBCPP_NODEBUG = signed char;124 125 _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}126 127public:128 static const weak_ordering less;129 static const weak_ordering equivalent;130 static const weak_ordering greater;131 132 _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {133 return __value_ == 0 ? partial_ordering::equivalent134 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);135 }136 137 // comparisons138 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;139 140 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {141 return __v.__value_ == 0;142 }143 144 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {145 return __v.__value_ < 0;146 }147 148 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {149 return __v.__value_ <= 0;150 }151 152 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {153 return __v.__value_ > 0;154 }155 156 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {157 return __v.__value_ >= 0;158 }159 160 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {161 return 0 < __v.__value_;162 }163 164 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {165 return 0 <= __v.__value_;166 }167 168 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {169 return 0 > __v.__value_;170 }171 172 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {173 return 0 >= __v.__value_;174 }175 176 _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {177 return __v;178 }179 180 _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {181 return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);182 }183 184private:185 _ValueT __value_;186};187 188inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);189inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv);190inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);191 192class strong_ordering {193 using _ValueT _LIBCPP_NODEBUG = signed char;194 195 _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}196 197public:198 static const strong_ordering less;199 static const strong_ordering equal;200 static const strong_ordering equivalent;201 static const strong_ordering greater;202 203 // conversions204 _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {205 return __value_ == 0 ? partial_ordering::equivalent206 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);207 }208 209 _LIBCPP_HIDE_FROM_ABI constexpr operator weak_ordering() const noexcept {210 return __value_ == 0 ? weak_ordering::equivalent : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);211 }212 213 // comparisons214 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;215 216 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {217 return __v.__value_ == 0;218 }219 220 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {221 return __v.__value_ < 0;222 }223 224 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {225 return __v.__value_ <= 0;226 }227 228 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {229 return __v.__value_ > 0;230 }231 232 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {233 return __v.__value_ >= 0;234 }235 236 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {237 return 0 < __v.__value_;238 }239 240 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {241 return 0 <= __v.__value_;242 }243 244 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {245 return 0 > __v.__value_;246 }247 248 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {249 return 0 >= __v.__value_;250 }251 252 _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering253 operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {254 return __v;255 }256 257 _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering258 operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {259 return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);260 }261 262private:263 _ValueT __value_;264};265 266inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);267inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);268inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);269inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);270 271/// [cmp.categories.pre]/1272/// The types partial_ordering, weak_ordering, and strong_ordering are273/// collectively termed the comparison category types.274template <class _Tp>275concept __comparison_category =276 is_same_v<_Tp, partial_ordering> || is_same_v<_Tp, weak_ordering> || is_same_v<_Tp, strong_ordering>;277 278#endif // _LIBCPP_STD_VER >= 20279 280_LIBCPP_END_NAMESPACE_STD281 282#endif // _LIBCPP___COMPARE_ORDERING_H283