Commit a2766235 by Charlie Beattie Committed by Copybara-Service

Add operator<=> comparison to absl::Time and absl::Duration.

PiperOrigin-RevId: 648433954
Change-Id: I32e47a89685419ae8d37dfadb354cfaab2a35ae9
parent 649f5892
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#include <array> #include <array>
#include <cfloat> #include <cfloat>
#include <chrono> // NOLINT(build/c++11) #include <chrono> // NOLINT(build/c++11)
#ifdef __cpp_impl_three_way_comparison
#include <compare>
#endif // __cpp_impl_three_way_comparison
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <ctime> #include <ctime>
...@@ -431,6 +436,15 @@ TEST(Duration, InfinityComparison) { ...@@ -431,6 +436,15 @@ TEST(Duration, InfinityComparison) {
EXPECT_LT(-inf, any_dur); EXPECT_LT(-inf, any_dur);
EXPECT_LT(-inf, inf); EXPECT_LT(-inf, inf);
EXPECT_GT(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) { TEST(Duration, InfinityAddition) {
...@@ -496,9 +510,20 @@ TEST(Duration, InfinitySubtraction) { ...@@ -496,9 +510,20 @@ TEST(Duration, InfinitySubtraction) {
// Interesting case // Interesting case
absl::Duration almost_neg_inf = sec_min; absl::Duration almost_neg_inf = sec_min;
EXPECT_LT(-inf, almost_neg_inf); 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); almost_neg_inf -= -absl::Nanoseconds(1);
EXPECT_LT(-inf, almost_neg_inf); 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 // For reference: IEEE 754 behavior
const double dbl_inf = std::numeric_limits<double>::infinity(); const double dbl_inf = std::numeric_limits<double>::infinity();
EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf
...@@ -857,6 +882,21 @@ TEST(Duration, Range) { ...@@ -857,6 +882,21 @@ TEST(Duration, Range) {
EXPECT_LT(neg_full_range, full_range); EXPECT_LT(neg_full_range, full_range);
EXPECT_EQ(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) { TEST(Duration, RelationalOperators) {
...@@ -880,6 +920,27 @@ TEST(Duration, RelationalOperators) { ...@@ -880,6 +920,27 @@ TEST(Duration, RelationalOperators) {
#undef TEST_REL_OPS #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) { TEST(Duration, Addition) {
#define TEST_ADD_OPS(UNIT) \ #define TEST_ADD_OPS(UNIT) \
do { \ do { \
......
...@@ -75,15 +75,22 @@ ...@@ -75,15 +75,22 @@
struct timeval; struct timeval;
#endif #endif
#include <chrono> // NOLINT(build/c++11) #include <chrono> // NOLINT(build/c++11)
#ifdef __cpp_impl_three_way_comparison
#include <compare>
#endif // __cpp_impl_three_way_comparison
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <ctime> #include <ctime>
#include <limits> #include <limits>
#include <ostream> #include <ostream>
#include <ratio> // NOLINT(build/c++11)
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -305,6 +312,14 @@ class Duration { ...@@ -305,6 +312,14 @@ class Duration {
}; };
// Relational Operators // 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, ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
Duration rhs); Duration rhs);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs, ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs,
...@@ -837,6 +852,11 @@ class Time { ...@@ -837,6 +852,11 @@ class Time {
private: private:
friend constexpr Time time_internal::FromUnixDuration(Duration d); friend constexpr Time time_internal::FromUnixDuration(Duration d);
friend constexpr Duration time_internal::ToUnixDuration(Time t); 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 constexpr bool operator==(Time lhs, Time rhs); friend constexpr bool operator==(Time lhs, Time rhs);
friend Duration operator-(Time lhs, Time rhs); friend Duration operator-(Time lhs, Time rhs);
...@@ -848,6 +868,15 @@ class Time { ...@@ -848,6 +868,15 @@ class Time {
}; };
// Relational Operators // 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) { ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
return lhs.rep_ < rhs.rep_; return lhs.rep_ < rhs.rep_;
} }
...@@ -1723,6 +1752,25 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, ...@@ -1723,6 +1752,25 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
: time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); : 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, ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
Duration rhs) { Duration rhs) {
return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) &&
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
#endif #endif
#include <chrono> // NOLINT(build/c++11) #include <chrono> // NOLINT(build/c++11)
#ifdef __cpp_impl_three_way_comparison
#include <compare>
#endif // __cpp_impl_three_way_comparison
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
...@@ -207,6 +212,22 @@ TEST(Time, RelationalOperators) { ...@@ -207,6 +212,22 @@ TEST(Time, RelationalOperators) {
static_assert(t3 >= t2, ""); static_assert(t3 >= t2, "");
static_assert(t1 >= t1, ""); static_assert(t1 >= t1, "");
static_assert(t3 >= 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) { TEST(Time, Infinity) {
...@@ -218,6 +239,15 @@ TEST(Time, Infinity) { ...@@ -218,6 +239,15 @@ TEST(Time, Infinity) {
static_assert(ipast < ifuture, ""); static_assert(ipast < ifuture, "");
static_assert(ifuture > ipast, ""); 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 // Arithmetic saturates
EXPECT_EQ(ifuture, ifuture + absl::Seconds(1)); EXPECT_EQ(ifuture, ifuture + absl::Seconds(1));
EXPECT_EQ(ifuture, ifuture - absl::Seconds(1)); EXPECT_EQ(ifuture, ifuture - absl::Seconds(1));
...@@ -233,6 +263,15 @@ TEST(Time, Infinity) { ...@@ -233,6 +263,15 @@ TEST(Time, Infinity) {
static_assert(t < ifuture, ""); static_assert(t < ifuture, "");
static_assert(t > ipast, ""); 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(ifuture, t + absl::InfiniteDuration());
EXPECT_EQ(ipast, t - absl::InfiniteDuration()); EXPECT_EQ(ipast, t - absl::InfiniteDuration());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment