00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef ABSL_TYPES_COMPARE_H_
00031 #define ABSL_TYPES_COMPARE_H_
00032
00033 #include <cstddef>
00034 #include <cstdint>
00035 #include <cstdlib>
00036 #include <type_traits>
00037
00038 #include "absl/base/attributes.h"
00039 #include "absl/meta/type_traits.h"
00040
00041 namespace absl {
00042 namespace compare_internal {
00043
00044 using value_type = int8_t;
00045
00046 template <typename T>
00047 struct Fail {
00048 static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
00049 };
00050
00051
00052
00053 template <typename NullPtrT = std::nullptr_t>
00054 struct OnlyLiteralZero {
00055 constexpr OnlyLiteralZero(NullPtrT) noexcept {}
00056
00057
00058
00059
00060
00061
00062 template <
00063 typename T,
00064 typename = typename std::enable_if<
00065 std::is_same<T, std::nullptr_t>::value ||
00066 (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
00067 typename = typename Fail<T>::type>
00068 OnlyLiteralZero(T);
00069 };
00070
00071 enum class eq : value_type {
00072 equal = 0,
00073 equivalent = equal,
00074 nonequal = 1,
00075 nonequivalent = nonequal,
00076 };
00077
00078 enum class ord : value_type { less = -1, greater = 1 };
00079
00080 enum class ncmp : value_type { unordered = -127 };
00081
00082
00083
00084
00085 template <typename T>
00086 struct weak_equality_base {
00087 ABSL_CONST_INIT static const T equivalent;
00088 ABSL_CONST_INIT static const T nonequivalent;
00089 };
00090 template <typename T>
00091 const T weak_equality_base<T>::equivalent(eq::equivalent);
00092 template <typename T>
00093 const T weak_equality_base<T>::nonequivalent(eq::nonequivalent);
00094
00095 template <typename T>
00096 struct strong_equality_base {
00097 ABSL_CONST_INIT static const T equal;
00098 ABSL_CONST_INIT static const T nonequal;
00099 ABSL_CONST_INIT static const T equivalent;
00100 ABSL_CONST_INIT static const T nonequivalent;
00101 };
00102 template <typename T>
00103 const T strong_equality_base<T>::equal(eq::equal);
00104 template <typename T>
00105 const T strong_equality_base<T>::nonequal(eq::nonequal);
00106 template <typename T>
00107 const T strong_equality_base<T>::equivalent(eq::equivalent);
00108 template <typename T>
00109 const T strong_equality_base<T>::nonequivalent(eq::nonequivalent);
00110
00111 template <typename T>
00112 struct partial_ordering_base {
00113 ABSL_CONST_INIT static const T less;
00114 ABSL_CONST_INIT static const T equivalent;
00115 ABSL_CONST_INIT static const T greater;
00116 ABSL_CONST_INIT static const T unordered;
00117 };
00118 template <typename T>
00119 const T partial_ordering_base<T>::less(ord::less);
00120 template <typename T>
00121 const T partial_ordering_base<T>::equivalent(eq::equivalent);
00122 template <typename T>
00123 const T partial_ordering_base<T>::greater(ord::greater);
00124 template <typename T>
00125 const T partial_ordering_base<T>::unordered(ncmp::unordered);
00126
00127 template <typename T>
00128 struct weak_ordering_base {
00129 ABSL_CONST_INIT static const T less;
00130 ABSL_CONST_INIT static const T equivalent;
00131 ABSL_CONST_INIT static const T greater;
00132 };
00133 template <typename T>
00134 const T weak_ordering_base<T>::less(ord::less);
00135 template <typename T>
00136 const T weak_ordering_base<T>::equivalent(eq::equivalent);
00137 template <typename T>
00138 const T weak_ordering_base<T>::greater(ord::greater);
00139
00140 template <typename T>
00141 struct strong_ordering_base {
00142 ABSL_CONST_INIT static const T less;
00143 ABSL_CONST_INIT static const T equal;
00144 ABSL_CONST_INIT static const T equivalent;
00145 ABSL_CONST_INIT static const T greater;
00146 };
00147 template <typename T>
00148 const T strong_ordering_base<T>::less(ord::less);
00149 template <typename T>
00150 const T strong_ordering_base<T>::equal(eq::equal);
00151 template <typename T>
00152 const T strong_ordering_base<T>::equivalent(eq::equivalent);
00153 template <typename T>
00154 const T strong_ordering_base<T>::greater(ord::greater);
00155
00156 }
00157
00158 class weak_equality
00159 : public compare_internal::weak_equality_base<weak_equality> {
00160 explicit constexpr weak_equality(compare_internal::eq v) noexcept
00161 : value_(static_cast<compare_internal::value_type>(v)) {}
00162 friend struct compare_internal::weak_equality_base<weak_equality>;
00163
00164 public:
00165
00166 friend constexpr bool operator==(
00167 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
00168 return v.value_ == 0;
00169 }
00170 friend constexpr bool operator!=(
00171 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
00172 return v.value_ != 0;
00173 }
00174 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
00175 weak_equality v) noexcept {
00176 return 0 == v.value_;
00177 }
00178 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
00179 weak_equality v) noexcept {
00180 return 0 != v.value_;
00181 }
00182
00183 private:
00184 compare_internal::value_type value_;
00185 };
00186
00187 class strong_equality
00188 : public compare_internal::strong_equality_base<strong_equality> {
00189 explicit constexpr strong_equality(compare_internal::eq v) noexcept
00190 : value_(static_cast<compare_internal::value_type>(v)) {}
00191 friend struct compare_internal::strong_equality_base<strong_equality>;
00192
00193 public:
00194
00195 constexpr operator weak_equality() const noexcept {
00196 return value_ == 0 ? weak_equality::equivalent
00197 : weak_equality::nonequivalent;
00198 }
00199
00200 friend constexpr bool operator==(
00201 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
00202 return v.value_ == 0;
00203 }
00204 friend constexpr bool operator!=(
00205 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
00206 return v.value_ != 0;
00207 }
00208 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
00209 strong_equality v) noexcept {
00210 return 0 == v.value_;
00211 }
00212 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
00213 strong_equality v) noexcept {
00214 return 0 != v.value_;
00215 }
00216
00217 private:
00218 compare_internal::value_type value_;
00219 };
00220
00221 class partial_ordering
00222 : public compare_internal::partial_ordering_base<partial_ordering> {
00223 explicit constexpr partial_ordering(compare_internal::eq v) noexcept
00224 : value_(static_cast<compare_internal::value_type>(v)) {}
00225 explicit constexpr partial_ordering(compare_internal::ord v) noexcept
00226 : value_(static_cast<compare_internal::value_type>(v)) {}
00227 explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
00228 : value_(static_cast<compare_internal::value_type>(v)) {}
00229 friend struct compare_internal::partial_ordering_base<partial_ordering>;
00230
00231 constexpr bool is_ordered() const noexcept {
00232 return value_ !=
00233 compare_internal::value_type(compare_internal::ncmp::unordered);
00234 }
00235
00236 public:
00237
00238 constexpr operator weak_equality() const noexcept {
00239 return value_ == 0 ? weak_equality::equivalent
00240 : weak_equality::nonequivalent;
00241 }
00242
00243 friend constexpr bool operator==(
00244 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00245 return v.is_ordered() && v.value_ == 0;
00246 }
00247 friend constexpr bool operator!=(
00248 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00249 return !v.is_ordered() || v.value_ != 0;
00250 }
00251 friend constexpr bool operator<(
00252 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00253 return v.is_ordered() && v.value_ < 0;
00254 }
00255 friend constexpr bool operator<=(
00256 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00257 return v.is_ordered() && v.value_ <= 0;
00258 }
00259 friend constexpr bool operator>(
00260 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00261 return v.is_ordered() && v.value_ > 0;
00262 }
00263 friend constexpr bool operator>=(
00264 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00265 return v.is_ordered() && v.value_ >= 0;
00266 }
00267 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
00268 partial_ordering v) noexcept {
00269 return v.is_ordered() && 0 == v.value_;
00270 }
00271 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
00272 partial_ordering v) noexcept {
00273 return !v.is_ordered() || 0 != v.value_;
00274 }
00275 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
00276 partial_ordering v) noexcept {
00277 return v.is_ordered() && 0 < v.value_;
00278 }
00279 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
00280 partial_ordering v) noexcept {
00281 return v.is_ordered() && 0 <= v.value_;
00282 }
00283 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
00284 partial_ordering v) noexcept {
00285 return v.is_ordered() && 0 > v.value_;
00286 }
00287 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
00288 partial_ordering v) noexcept {
00289 return v.is_ordered() && 0 >= v.value_;
00290 }
00291
00292 private:
00293 compare_internal::value_type value_;
00294 };
00295
00296 class weak_ordering
00297 : public compare_internal::weak_ordering_base<weak_ordering> {
00298 explicit constexpr weak_ordering(compare_internal::eq v) noexcept
00299 : value_(static_cast<compare_internal::value_type>(v)) {}
00300 explicit constexpr weak_ordering(compare_internal::ord v) noexcept
00301 : value_(static_cast<compare_internal::value_type>(v)) {}
00302 friend struct compare_internal::weak_ordering_base<weak_ordering>;
00303
00304 public:
00305
00306 constexpr operator weak_equality() const noexcept {
00307 return value_ == 0 ? weak_equality::equivalent
00308 : weak_equality::nonequivalent;
00309 }
00310 constexpr operator partial_ordering() const noexcept {
00311 return value_ == 0 ? partial_ordering::equivalent
00312 : (value_ < 0 ? partial_ordering::less
00313 : partial_ordering::greater);
00314 }
00315
00316 friend constexpr bool operator==(
00317 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00318 return v.value_ == 0;
00319 }
00320 friend constexpr bool operator!=(
00321 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00322 return v.value_ != 0;
00323 }
00324 friend constexpr bool operator<(
00325 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00326 return v.value_ < 0;
00327 }
00328 friend constexpr bool operator<=(
00329 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00330 return v.value_ <= 0;
00331 }
00332 friend constexpr bool operator>(
00333 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00334 return v.value_ > 0;
00335 }
00336 friend constexpr bool operator>=(
00337 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00338 return v.value_ >= 0;
00339 }
00340 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
00341 weak_ordering v) noexcept {
00342 return 0 == v.value_;
00343 }
00344 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
00345 weak_ordering v) noexcept {
00346 return 0 != v.value_;
00347 }
00348 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
00349 weak_ordering v) noexcept {
00350 return 0 < v.value_;
00351 }
00352 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
00353 weak_ordering v) noexcept {
00354 return 0 <= v.value_;
00355 }
00356 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
00357 weak_ordering v) noexcept {
00358 return 0 > v.value_;
00359 }
00360 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
00361 weak_ordering v) noexcept {
00362 return 0 >= v.value_;
00363 }
00364
00365 private:
00366 compare_internal::value_type value_;
00367 };
00368
00369 class strong_ordering
00370 : public compare_internal::strong_ordering_base<strong_ordering> {
00371 explicit constexpr strong_ordering(compare_internal::eq v) noexcept
00372 : value_(static_cast<compare_internal::value_type>(v)) {}
00373 explicit constexpr strong_ordering(compare_internal::ord v) noexcept
00374 : value_(static_cast<compare_internal::value_type>(v)) {}
00375 friend struct compare_internal::strong_ordering_base<strong_ordering>;
00376
00377 public:
00378
00379 constexpr operator weak_equality() const noexcept {
00380 return value_ == 0 ? weak_equality::equivalent
00381 : weak_equality::nonequivalent;
00382 }
00383 constexpr operator strong_equality() const noexcept {
00384 return value_ == 0 ? strong_equality::equal : strong_equality::nonequal;
00385 }
00386 constexpr operator partial_ordering() const noexcept {
00387 return value_ == 0 ? partial_ordering::equivalent
00388 : (value_ < 0 ? partial_ordering::less
00389 : partial_ordering::greater);
00390 }
00391 constexpr operator weak_ordering() const noexcept {
00392 return value_ == 0
00393 ? weak_ordering::equivalent
00394 : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
00395 }
00396
00397 friend constexpr bool operator==(
00398 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00399 return v.value_ == 0;
00400 }
00401 friend constexpr bool operator!=(
00402 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00403 return v.value_ != 0;
00404 }
00405 friend constexpr bool operator<(
00406 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00407 return v.value_ < 0;
00408 }
00409 friend constexpr bool operator<=(
00410 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00411 return v.value_ <= 0;
00412 }
00413 friend constexpr bool operator>(
00414 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00415 return v.value_ > 0;
00416 }
00417 friend constexpr bool operator>=(
00418 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
00419 return v.value_ >= 0;
00420 }
00421 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
00422 strong_ordering v) noexcept {
00423 return 0 == v.value_;
00424 }
00425 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
00426 strong_ordering v) noexcept {
00427 return 0 != v.value_;
00428 }
00429 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
00430 strong_ordering v) noexcept {
00431 return 0 < v.value_;
00432 }
00433 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
00434 strong_ordering v) noexcept {
00435 return 0 <= v.value_;
00436 }
00437 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
00438 strong_ordering v) noexcept {
00439 return 0 > v.value_;
00440 }
00441 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
00442 strong_ordering v) noexcept {
00443 return 0 >= v.value_;
00444 }
00445
00446 private:
00447 compare_internal::value_type value_;
00448 };
00449
00450 namespace compare_internal {
00451
00452
00453
00454
00455
00456 template <typename Bool,
00457 absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0>
00458 constexpr bool compare_result_as_less_than(const Bool r) { return r; }
00459 constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
00460 return r < 0;
00461 }
00462
00463 template <typename Compare, typename K, typename LK>
00464 constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
00465 const LK &y) {
00466 return compare_result_as_less_than(compare(x, y));
00467 }
00468
00469
00470
00471
00472 template <typename Int,
00473 absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
00474 constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
00475 return c < 0 ? absl::weak_ordering::less
00476 : c == 0 ? absl::weak_ordering::equivalent
00477 : absl::weak_ordering::greater;
00478 }
00479 constexpr absl::weak_ordering compare_result_as_ordering(
00480 const absl::weak_ordering c) {
00481 return c;
00482 }
00483
00484 template <
00485 typename Compare, typename K, typename LK,
00486 absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
00487 const K &, const LK &)>>::value,
00488 int> = 0>
00489 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
00490 const K &x, const LK &y) {
00491 return compare_result_as_ordering(compare(x, y));
00492 }
00493 template <
00494 typename Compare, typename K, typename LK,
00495 absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
00496 const K &, const LK &)>>::value,
00497 int> = 0>
00498 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
00499 const K &x, const LK &y) {
00500 return compare(x, y) ? absl::weak_ordering::less
00501 : compare(y, x) ? absl::weak_ordering::greater
00502 : absl::weak_ordering::equivalent;
00503 }
00504
00505 }
00506 }
00507
00508 #endif // ABSL_TYPES_COMPARE_H_