Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:31

0001 // Copyright 2018 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // -----------------------------------------------------------------------------
0016 // compare.h
0017 // -----------------------------------------------------------------------------
0018 //
0019 // This header file defines the `absl::partial_ordering`, `absl::weak_ordering`,
0020 // and `absl::strong_ordering` types for storing the results of three way
0021 // comparisons.
0022 //
0023 // Example:
0024 //   absl::weak_ordering compare(const std::string& a, const std::string& b);
0025 //
0026 // These are C++11 compatible versions of the C++20 corresponding types
0027 // (`std::partial_ordering`, etc.) and are designed to be drop-in replacements
0028 // for code compliant with C++20.
0029 
0030 #ifndef ABSL_TYPES_COMPARE_H_
0031 #define ABSL_TYPES_COMPARE_H_
0032 
0033 #include "absl/base/config.h"
0034 
0035 #ifdef ABSL_USES_STD_ORDERING
0036 
0037 #include <compare>  // IWYU pragma: export
0038 #include <type_traits>
0039 
0040 #include "absl/meta/type_traits.h"
0041 
0042 #else
0043 
0044 #include <cstddef>
0045 #include <cstdint>
0046 #include <cstdlib>
0047 #include <type_traits>
0048 
0049 #include "absl/base/attributes.h"
0050 #include "absl/base/macros.h"
0051 #include "absl/meta/type_traits.h"
0052 
0053 #endif
0054 
0055 namespace absl {
0056 ABSL_NAMESPACE_BEGIN
0057 
0058 #ifdef ABSL_USES_STD_ORDERING
0059 
0060 using std::partial_ordering;
0061 using std::strong_ordering;
0062 using std::weak_ordering;
0063 
0064 #else
0065 
0066 namespace compare_internal {
0067 
0068 using value_type = int8_t;
0069 
0070 class OnlyLiteralZero {
0071  public:
0072 #if ABSL_HAVE_ATTRIBUTE(enable_if)
0073   // On clang, we can avoid triggering modernize-use-nullptr by only enabling
0074   // this overload when the value is a compile time integer constant equal to 0.
0075   //
0076   // In c++20, this could be a static_assert in a consteval function.
0077   constexpr OnlyLiteralZero(int n)  // NOLINT
0078       __attribute__((enable_if(n == 0, "Only literal `0` is allowed."))) {}
0079 #else  // ABSL_HAVE_ATTRIBUTE(enable_if)
0080   // Accept only literal zero since it can be implicitly converted to a pointer
0081   // to member type. nullptr constants will be caught by the other constructor
0082   // which accepts a nullptr_t.
0083   //
0084   // This constructor is not used for clang since it triggers
0085   // modernize-use-nullptr.
0086   constexpr OnlyLiteralZero(int OnlyLiteralZero::*) noexcept {}  // NOLINT
0087 #endif
0088 
0089   // Fails compilation when `nullptr` or integral type arguments other than
0090   // `int` are passed. This constructor doesn't accept `int` because literal `0`
0091   // has type `int`. Literal `0` arguments will be implicitly converted to
0092   // `std::nullptr_t` and accepted by the above constructor, while other `int`
0093   // arguments will fail to be converted and cause compilation failure.
0094   template <typename T, typename = typename std::enable_if<
0095                             std::is_same<T, std::nullptr_t>::value ||
0096                             (std::is_integral<T>::value &&
0097                              !std::is_same<T, int>::value)>::type>
0098   OnlyLiteralZero(T) {  // NOLINT
0099     static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
0100   }
0101 };
0102 
0103 enum class eq : value_type {
0104   equal = 0,
0105   equivalent = equal,
0106   nonequal = 1,
0107   nonequivalent = nonequal,
0108 };
0109 
0110 enum class ord : value_type { less = -1, greater = 1 };
0111 
0112 enum class ncmp : value_type { unordered = -127 };
0113 
0114 // Define macros to allow for creation or emulation of C++17 inline variables
0115 // based on whether the feature is supported. Note: we can't use
0116 // ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of
0117 // incomplete types so they need to be defined after the types are complete.
0118 #ifdef __cpp_inline_variables
0119 
0120 // A no-op expansion that can be followed by a semicolon at class level.
0121 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "")
0122 
0123 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
0124   static const type name
0125 
0126 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \
0127   inline constexpr type type::name(init)
0128 
0129 #else  // __cpp_inline_variables
0130 
0131 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \
0132   ABSL_CONST_INIT static const T name
0133 
0134 // A no-op expansion that can be followed by a semicolon at class level.
0135 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "")
0136 
0137 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \
0138   template <typename T>                            \
0139   const T compare_internal::type##_base<T>::name(init)
0140 
0141 #endif  // __cpp_inline_variables
0142 
0143 // These template base classes allow for defining the values of the constants
0144 // in the header file (for performance) without using inline variables (which
0145 // aren't available in C++11).
0146 template <typename T>
0147 struct partial_ordering_base {
0148   ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
0149   ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
0150   ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
0151   ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered);
0152 };
0153 
0154 template <typename T>
0155 struct weak_ordering_base {
0156   ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
0157   ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
0158   ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
0159 };
0160 
0161 template <typename T>
0162 struct strong_ordering_base {
0163   ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
0164   ABSL_COMPARE_INLINE_BASECLASS_DECL(equal);
0165   ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
0166   ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
0167 };
0168 
0169 }  // namespace compare_internal
0170 
0171 class partial_ordering
0172     : public compare_internal::partial_ordering_base<partial_ordering> {
0173   explicit constexpr partial_ordering(compare_internal::eq v) noexcept
0174       : value_(static_cast<compare_internal::value_type>(v)) {}
0175   explicit constexpr partial_ordering(compare_internal::ord v) noexcept
0176       : value_(static_cast<compare_internal::value_type>(v)) {}
0177   explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
0178       : value_(static_cast<compare_internal::value_type>(v)) {}
0179   friend struct compare_internal::partial_ordering_base<partial_ordering>;
0180 
0181   constexpr bool is_ordered() const noexcept {
0182     return value_ !=
0183            compare_internal::value_type(compare_internal::ncmp::unordered);
0184   }
0185 
0186  public:
0187   ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less);
0188   ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent);
0189   ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater);
0190   ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered);
0191 
0192   // Comparisons
0193   friend constexpr bool operator==(
0194       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0195     return v.is_ordered() && v.value_ == 0;
0196   }
0197   friend constexpr bool operator!=(
0198       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0199     return !v.is_ordered() || v.value_ != 0;
0200   }
0201   friend constexpr bool operator<(
0202       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0203     return v.is_ordered() && v.value_ < 0;
0204   }
0205   friend constexpr bool operator<=(
0206       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0207     return v.is_ordered() && v.value_ <= 0;
0208   }
0209   friend constexpr bool operator>(
0210       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0211     return v.is_ordered() && v.value_ > 0;
0212   }
0213   friend constexpr bool operator>=(
0214       partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0215     return v.is_ordered() && v.value_ >= 0;
0216   }
0217   friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
0218                                    partial_ordering v) noexcept {
0219     return v.is_ordered() && 0 == v.value_;
0220   }
0221   friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
0222                                    partial_ordering v) noexcept {
0223     return !v.is_ordered() || 0 != v.value_;
0224   }
0225   friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
0226                                   partial_ordering v) noexcept {
0227     return v.is_ordered() && 0 < v.value_;
0228   }
0229   friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
0230                                    partial_ordering v) noexcept {
0231     return v.is_ordered() && 0 <= v.value_;
0232   }
0233   friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
0234                                   partial_ordering v) noexcept {
0235     return v.is_ordered() && 0 > v.value_;
0236   }
0237   friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
0238                                    partial_ordering v) noexcept {
0239     return v.is_ordered() && 0 >= v.value_;
0240   }
0241   friend constexpr bool operator==(partial_ordering v1,
0242                                    partial_ordering v2) noexcept {
0243     return v1.value_ == v2.value_;
0244   }
0245   friend constexpr bool operator!=(partial_ordering v1,
0246                                    partial_ordering v2) noexcept {
0247     return v1.value_ != v2.value_;
0248   }
0249 
0250  private:
0251   compare_internal::value_type value_;
0252 };
0253 ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less);
0254 ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent,
0255                          compare_internal::eq::equivalent);
0256 ABSL_COMPARE_INLINE_INIT(partial_ordering, greater,
0257                          compare_internal::ord::greater);
0258 ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered,
0259                          compare_internal::ncmp::unordered);
0260 
0261 class weak_ordering
0262     : public compare_internal::weak_ordering_base<weak_ordering> {
0263   explicit constexpr weak_ordering(compare_internal::eq v) noexcept
0264       : value_(static_cast<compare_internal::value_type>(v)) {}
0265   explicit constexpr weak_ordering(compare_internal::ord v) noexcept
0266       : value_(static_cast<compare_internal::value_type>(v)) {}
0267   friend struct compare_internal::weak_ordering_base<weak_ordering>;
0268 
0269  public:
0270   ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less);
0271   ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent);
0272   ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater);
0273 
0274   // Conversions
0275   constexpr operator partial_ordering() const noexcept {  // NOLINT
0276     return value_ == 0 ? partial_ordering::equivalent
0277                        : (value_ < 0 ? partial_ordering::less
0278                                      : partial_ordering::greater);
0279   }
0280   // Comparisons
0281   friend constexpr bool operator==(
0282       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0283     return v.value_ == 0;
0284   }
0285   friend constexpr bool operator!=(
0286       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0287     return v.value_ != 0;
0288   }
0289   friend constexpr bool operator<(
0290       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0291     return v.value_ < 0;
0292   }
0293   friend constexpr bool operator<=(
0294       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0295     return v.value_ <= 0;
0296   }
0297   friend constexpr bool operator>(
0298       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0299     return v.value_ > 0;
0300   }
0301   friend constexpr bool operator>=(
0302       weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0303     return v.value_ >= 0;
0304   }
0305   friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
0306                                    weak_ordering v) noexcept {
0307     return 0 == v.value_;
0308   }
0309   friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
0310                                    weak_ordering v) noexcept {
0311     return 0 != v.value_;
0312   }
0313   friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
0314                                   weak_ordering v) noexcept {
0315     return 0 < v.value_;
0316   }
0317   friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
0318                                    weak_ordering v) noexcept {
0319     return 0 <= v.value_;
0320   }
0321   friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
0322                                   weak_ordering v) noexcept {
0323     return 0 > v.value_;
0324   }
0325   friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
0326                                    weak_ordering v) noexcept {
0327     return 0 >= v.value_;
0328   }
0329   friend constexpr bool operator==(weak_ordering v1,
0330                                    weak_ordering v2) noexcept {
0331     return v1.value_ == v2.value_;
0332   }
0333   friend constexpr bool operator!=(weak_ordering v1,
0334                                    weak_ordering v2) noexcept {
0335     return v1.value_ != v2.value_;
0336   }
0337 
0338  private:
0339   compare_internal::value_type value_;
0340 };
0341 ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less);
0342 ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent,
0343                          compare_internal::eq::equivalent);
0344 ABSL_COMPARE_INLINE_INIT(weak_ordering, greater,
0345                          compare_internal::ord::greater);
0346 
0347 class strong_ordering
0348     : public compare_internal::strong_ordering_base<strong_ordering> {
0349   explicit constexpr strong_ordering(compare_internal::eq v) noexcept
0350       : value_(static_cast<compare_internal::value_type>(v)) {}
0351   explicit constexpr strong_ordering(compare_internal::ord v) noexcept
0352       : value_(static_cast<compare_internal::value_type>(v)) {}
0353   friend struct compare_internal::strong_ordering_base<strong_ordering>;
0354 
0355  public:
0356   ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less);
0357   ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal);
0358   ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent);
0359   ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater);
0360 
0361   // Conversions
0362   constexpr operator partial_ordering() const noexcept {  // NOLINT
0363     return value_ == 0 ? partial_ordering::equivalent
0364                        : (value_ < 0 ? partial_ordering::less
0365                                      : partial_ordering::greater);
0366   }
0367   constexpr operator weak_ordering() const noexcept {  // NOLINT
0368     return value_ == 0
0369                ? weak_ordering::equivalent
0370                : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
0371   }
0372   // Comparisons
0373   friend constexpr bool operator==(
0374       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0375     return v.value_ == 0;
0376   }
0377   friend constexpr bool operator!=(
0378       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0379     return v.value_ != 0;
0380   }
0381   friend constexpr bool operator<(
0382       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0383     return v.value_ < 0;
0384   }
0385   friend constexpr bool operator<=(
0386       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0387     return v.value_ <= 0;
0388   }
0389   friend constexpr bool operator>(
0390       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0391     return v.value_ > 0;
0392   }
0393   friend constexpr bool operator>=(
0394       strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
0395     return v.value_ >= 0;
0396   }
0397   friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
0398                                    strong_ordering v) noexcept {
0399     return 0 == v.value_;
0400   }
0401   friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
0402                                    strong_ordering v) noexcept {
0403     return 0 != v.value_;
0404   }
0405   friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
0406                                   strong_ordering v) noexcept {
0407     return 0 < v.value_;
0408   }
0409   friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
0410                                    strong_ordering v) noexcept {
0411     return 0 <= v.value_;
0412   }
0413   friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
0414                                   strong_ordering v) noexcept {
0415     return 0 > v.value_;
0416   }
0417   friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
0418                                    strong_ordering v) noexcept {
0419     return 0 >= v.value_;
0420   }
0421   friend constexpr bool operator==(strong_ordering v1,
0422                                    strong_ordering v2) noexcept {
0423     return v1.value_ == v2.value_;
0424   }
0425   friend constexpr bool operator!=(strong_ordering v1,
0426                                    strong_ordering v2) noexcept {
0427     return v1.value_ != v2.value_;
0428   }
0429 
0430  private:
0431   compare_internal::value_type value_;
0432 };
0433 ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less);
0434 ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal);
0435 ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent,
0436                          compare_internal::eq::equivalent);
0437 ABSL_COMPARE_INLINE_INIT(strong_ordering, greater,
0438                          compare_internal::ord::greater);
0439 
0440 #undef ABSL_COMPARE_INLINE_BASECLASS_DECL
0441 #undef ABSL_COMPARE_INLINE_SUBCLASS_DECL
0442 #undef ABSL_COMPARE_INLINE_INIT
0443 
0444 #endif  // ABSL_USES_STD_ORDERING
0445 
0446 namespace compare_internal {
0447 // We also provide these comparator adapter functions for internal absl use.
0448 
0449 // Helper functions to do a boolean comparison of two keys given a boolean
0450 // or three-way comparator.
0451 // SFINAE prevents implicit conversions to bool (such as from int).
0452 template <typename BoolT,
0453           absl::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0>
0454 constexpr bool compare_result_as_less_than(const BoolT r) { return r; }
0455 constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
0456   return r < 0;
0457 }
0458 
0459 template <typename Compare, typename K, typename LK>
0460 constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
0461                                        const LK &y) {
0462   return compare_result_as_less_than(compare(x, y));
0463 }
0464 
0465 // Helper functions to do a three-way comparison of two keys given a boolean or
0466 // three-way comparator.
0467 // SFINAE prevents implicit conversions to int (such as from bool).
0468 template <typename Int,
0469           absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
0470 constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
0471   return c < 0 ? absl::weak_ordering::less
0472                : c == 0 ? absl::weak_ordering::equivalent
0473                         : absl::weak_ordering::greater;
0474 }
0475 constexpr absl::weak_ordering compare_result_as_ordering(
0476     const absl::weak_ordering c) {
0477   return c;
0478 }
0479 
0480 template <
0481     typename Compare, typename K, typename LK,
0482     absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
0483                                               const K &, const LK &)>>::value,
0484                       int> = 0>
0485 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
0486                                                       const K &x, const LK &y) {
0487   return compare_result_as_ordering(compare(x, y));
0488 }
0489 template <
0490     typename Compare, typename K, typename LK,
0491     absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
0492                                              const K &, const LK &)>>::value,
0493                       int> = 0>
0494 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
0495                                                       const K &x, const LK &y) {
0496   return compare(x, y) ? absl::weak_ordering::less
0497                        : compare(y, x) ? absl::weak_ordering::greater
0498                                        : absl::weak_ordering::equivalent;
0499 }
0500 
0501 }  // namespace compare_internal
0502 ABSL_NAMESPACE_END
0503 }  // namespace absl
0504 
0505 #endif  // ABSL_TYPES_COMPARE_H_