diff options
author | Charlie Beattie <cbeattie@google.com> | 2024-07-01 11:31:14 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-07-01 11:31:52 -0700 |
commit | a27662352e9caafc264747562162a8a32ef36cb9 (patch) | |
tree | a894acd86b3b736767c67f78db58d519e196e8f7 /absl | |
parent | 649f58927db8f223098be81ab5d8a70469848806 (diff) |
Add operator<=> comparison to absl::Time and absl::Duration.
PiperOrigin-RevId: 648433954
Change-Id: I32e47a89685419ae8d37dfadb354cfaab2a35ae9
Diffstat (limited to 'absl')
-rw-r--r-- | absl/time/duration_test.cc | 61 | ||||
-rw-r--r-- | absl/time/time.h | 48 | ||||
-rw-r--r-- | absl/time/time_test.cc | 39 |
3 files changed, 148 insertions, 0 deletions
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index dcf7aad6..4c801a8d 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -19,6 +19,11 @@ #include <array> #include <cfloat> #include <chrono> // NOLINT(build/c++11) + +#ifdef __cpp_impl_three_way_comparison +#include <compare> +#endif // __cpp_impl_three_way_comparison + #include <cmath> #include <cstdint> #include <ctime> @@ -431,6 +436,15 @@ TEST(Duration, InfinityComparison) { EXPECT_LT(-inf, any_dur); EXPECT_LT(-inf, inf); EXPECT_GT(inf, -inf); + +#ifdef __cpp_impl_three_way_comparison + EXPECT_EQ(inf <=> inf, std::strong_ordering::equal); + EXPECT_EQ(-inf <=> -inf, std::strong_ordering::equal); + EXPECT_EQ(-inf <=> inf, std::strong_ordering::less); + EXPECT_EQ(inf <=> -inf, std::strong_ordering::greater); + EXPECT_EQ(any_dur <=> inf, std::strong_ordering::less); + EXPECT_EQ(any_dur <=> -inf, std::strong_ordering::greater); +#endif // __cpp_impl_three_way_comparison } TEST(Duration, InfinityAddition) { @@ -496,9 +510,20 @@ TEST(Duration, InfinitySubtraction) { // Interesting case absl::Duration almost_neg_inf = sec_min; EXPECT_LT(-inf, almost_neg_inf); + +#ifdef __cpp_impl_three_way_comparison + EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less); + EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater); +#endif // __cpp_impl_three_way_comparison + almost_neg_inf -= -absl::Nanoseconds(1); EXPECT_LT(-inf, almost_neg_inf); +#ifdef __cpp_impl_three_way_comparison + EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less); + EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater); +#endif // __cpp_impl_three_way_comparison + // For reference: IEEE 754 behavior const double dbl_inf = std::numeric_limits<double>::infinity(); EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf @@ -857,6 +882,21 @@ TEST(Duration, Range) { EXPECT_LT(neg_full_range, full_range); EXPECT_EQ(neg_full_range, -full_range); + +#ifdef __cpp_impl_three_way_comparison + EXPECT_EQ(range_future <=> absl::InfiniteDuration(), + std::strong_ordering::less); + EXPECT_EQ(range_past <=> -absl::InfiniteDuration(), + std::strong_ordering::greater); + EXPECT_EQ(full_range <=> absl::ZeroDuration(), // + std::strong_ordering::greater); + EXPECT_EQ(full_range <=> -absl::InfiniteDuration(), + std::strong_ordering::greater); + EXPECT_EQ(neg_full_range <=> -absl::InfiniteDuration(), + std::strong_ordering::greater); + EXPECT_EQ(neg_full_range <=> full_range, std::strong_ordering::less); + EXPECT_EQ(neg_full_range <=> -full_range, std::strong_ordering::equal); +#endif // __cpp_impl_three_way_comparison } TEST(Duration, RelationalOperators) { @@ -880,6 +920,27 @@ TEST(Duration, RelationalOperators) { #undef TEST_REL_OPS } + +#ifdef __cpp_impl_three_way_comparison + +TEST(Duration, SpaceshipOperators) { +#define TEST_REL_OPS(UNIT) \ + static_assert(UNIT(2) <=> UNIT(2) == std::strong_ordering::equal, ""); \ + static_assert(UNIT(1) <=> UNIT(2) == std::strong_ordering::less, ""); \ + static_assert(UNIT(3) <=> UNIT(2) == std::strong_ordering::greater, ""); + + TEST_REL_OPS(absl::Nanoseconds); + TEST_REL_OPS(absl::Microseconds); + TEST_REL_OPS(absl::Milliseconds); + TEST_REL_OPS(absl::Seconds); + TEST_REL_OPS(absl::Minutes); + TEST_REL_OPS(absl::Hours); + +#undef TEST_REL_OPS +} + +#endif // __cpp_impl_three_way_comparison + TEST(Duration, Addition) { #define TEST_ADD_OPS(UNIT) \ do { \ diff --git a/absl/time/time.h b/absl/time/time.h index d367ace2..f133c2d2 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -75,15 +75,22 @@ struct timeval; #endif #include <chrono> // NOLINT(build/c++11) + +#ifdef __cpp_impl_three_way_comparison +#include <compare> +#endif // __cpp_impl_three_way_comparison + #include <cmath> #include <cstdint> #include <ctime> #include <limits> #include <ostream> +#include <ratio> // NOLINT(build/c++11) #include <string> #include <type_traits> #include <utility> +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/strings/string_view.h" @@ -305,6 +312,14 @@ class Duration { }; // Relational Operators + +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Duration lhs, Duration rhs); + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, Duration rhs); ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs, @@ -837,6 +852,11 @@ class Time { private: friend constexpr Time time_internal::FromUnixDuration(Duration d); friend constexpr Duration time_internal::ToUnixDuration(Time t); + +#ifdef __cpp_impl_three_way_comparison + friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs); +#endif // __cpp_impl_three_way_comparison + friend constexpr bool operator<(Time lhs, Time rhs); friend constexpr bool operator==(Time lhs, Time rhs); friend Duration operator-(Time lhs, Time rhs); @@ -848,6 +868,15 @@ class Time { }; // Relational Operators +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Time lhs, Time rhs) { + return lhs.rep_ <=> rhs.rep_; +} + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; } @@ -1723,6 +1752,25 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); } + +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Duration lhs, Duration rhs) { + const int64_t lhs_hi = time_internal::GetRepHi(lhs); + const int64_t rhs_hi = time_internal::GetRepHi(rhs); + if (auto c = lhs_hi <=> rhs_hi; c != std::strong_ordering::equal) { + return c; + } + const uint32_t lhs_lo = time_internal::GetRepLo(lhs); + const uint32_t rhs_lo = time_internal::GetRepLo(rhs); + return (lhs_hi == (std::numeric_limits<int64_t>::min)()) + ? (lhs_lo + 1) <=> (rhs_lo + 1) + : lhs_lo <=> rhs_lo; +} + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs, Duration rhs) { return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index 052d8806..71f54d64 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -24,6 +24,11 @@ #endif #include <chrono> // NOLINT(build/c++11) + +#ifdef __cpp_impl_three_way_comparison +#include <compare> +#endif // __cpp_impl_three_way_comparison + #include <cstring> #include <ctime> #include <iomanip> @@ -207,6 +212,22 @@ TEST(Time, RelationalOperators) { static_assert(t3 >= t2, ""); static_assert(t1 >= t1, ""); static_assert(t3 >= t1, ""); + +#ifdef __cpp_impl_three_way_comparison + + static_assert((t1 <=> t1) == std::strong_ordering::equal, ""); + static_assert((t2 <=> t2) == std::strong_ordering::equal, ""); + static_assert((t3 <=> t3) == std::strong_ordering::equal, ""); + + static_assert((t1 <=> t2) == std::strong_ordering::less, ""); + static_assert((t2 <=> t3) == std::strong_ordering::less, ""); + static_assert((t1 <=> t3) == std::strong_ordering::less, ""); + + static_assert((t2 <=> t1) == std::strong_ordering::greater, ""); + static_assert((t3 <=> t2) == std::strong_ordering::greater, ""); + static_assert((t3 <=> t1) == std::strong_ordering::greater, ""); + +#endif // __cpp_impl_three_way_comparison } TEST(Time, Infinity) { @@ -218,6 +239,15 @@ TEST(Time, Infinity) { static_assert(ipast < ifuture, ""); static_assert(ifuture > ipast, ""); +#ifdef __cpp_impl_three_way_comparison + + static_assert((ifuture <=> ifuture) == std::strong_ordering::equal, ""); + static_assert((ipast <=> ipast) == std::strong_ordering::equal, ""); + static_assert((ipast <=> ifuture) == std::strong_ordering::less, ""); + static_assert((ifuture <=> ipast) == std::strong_ordering::greater, ""); + +#endif // __cpp_impl_three_way_comparison + // Arithmetic saturates EXPECT_EQ(ifuture, ifuture + absl::Seconds(1)); EXPECT_EQ(ifuture, ifuture - absl::Seconds(1)); @@ -233,6 +263,15 @@ TEST(Time, Infinity) { static_assert(t < ifuture, ""); static_assert(t > ipast, ""); +#ifdef __cpp_impl_three_way_comparison + + static_assert((t <=> ifuture) == std::strong_ordering::less, ""); + static_assert((t <=> ipast) == std::strong_ordering::greater, ""); + static_assert((ipast <=> t) == std::strong_ordering::less, ""); + static_assert((ifuture <=> t) == std::strong_ordering::greater, ""); + +#endif // __cpp_impl_three_way_comparison + EXPECT_EQ(ifuture, t + absl::InfiniteDuration()); EXPECT_EQ(ipast, t - absl::InfiniteDuration()); } |