Skip to content

Commit a276623

Browse files
charlesbeattiecopybara-github
authored andcommitted
Add operator<=> comparison to absl::Time and absl::Duration.
PiperOrigin-RevId: 648433954 Change-Id: I32e47a89685419ae8d37dfadb354cfaab2a35ae9
1 parent 649f589 commit a276623

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

absl/time/duration_test.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
#include <array>
2020
#include <cfloat>
2121
#include <chrono> // NOLINT(build/c++11)
22+
23+
#ifdef __cpp_impl_three_way_comparison
24+
#include <compare>
25+
#endif // __cpp_impl_three_way_comparison
26+
2227
#include <cmath>
2328
#include <cstdint>
2429
#include <ctime>
@@ -431,6 +436,15 @@ TEST(Duration, InfinityComparison) {
431436
EXPECT_LT(-inf, any_dur);
432437
EXPECT_LT(-inf, inf);
433438
EXPECT_GT(inf, -inf);
439+
440+
#ifdef __cpp_impl_three_way_comparison
441+
EXPECT_EQ(inf <=> inf, std::strong_ordering::equal);
442+
EXPECT_EQ(-inf <=> -inf, std::strong_ordering::equal);
443+
EXPECT_EQ(-inf <=> inf, std::strong_ordering::less);
444+
EXPECT_EQ(inf <=> -inf, std::strong_ordering::greater);
445+
EXPECT_EQ(any_dur <=> inf, std::strong_ordering::less);
446+
EXPECT_EQ(any_dur <=> -inf, std::strong_ordering::greater);
447+
#endif // __cpp_impl_three_way_comparison
434448
}
435449

436450
TEST(Duration, InfinityAddition) {
@@ -496,9 +510,20 @@ TEST(Duration, InfinitySubtraction) {
496510
// Interesting case
497511
absl::Duration almost_neg_inf = sec_min;
498512
EXPECT_LT(-inf, almost_neg_inf);
513+
514+
#ifdef __cpp_impl_three_way_comparison
515+
EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);
516+
EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);
517+
#endif // __cpp_impl_three_way_comparison
518+
499519
almost_neg_inf -= -absl::Nanoseconds(1);
500520
EXPECT_LT(-inf, almost_neg_inf);
501521

522+
#ifdef __cpp_impl_three_way_comparison
523+
EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);
524+
EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);
525+
#endif // __cpp_impl_three_way_comparison
526+
502527
// For reference: IEEE 754 behavior
503528
const double dbl_inf = std::numeric_limits<double>::infinity();
504529
EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf
@@ -857,6 +882,21 @@ TEST(Duration, Range) {
857882

858883
EXPECT_LT(neg_full_range, full_range);
859884
EXPECT_EQ(neg_full_range, -full_range);
885+
886+
#ifdef __cpp_impl_three_way_comparison
887+
EXPECT_EQ(range_future <=> absl::InfiniteDuration(),
888+
std::strong_ordering::less);
889+
EXPECT_EQ(range_past <=> -absl::InfiniteDuration(),
890+
std::strong_ordering::greater);
891+
EXPECT_EQ(full_range <=> absl::ZeroDuration(), //
892+
std::strong_ordering::greater);
893+
EXPECT_EQ(full_range <=> -absl::InfiniteDuration(),
894+
std::strong_ordering::greater);
895+
EXPECT_EQ(neg_full_range <=> -absl::InfiniteDuration(),
896+
std::strong_ordering::greater);
897+
EXPECT_EQ(neg_full_range <=> full_range, std::strong_ordering::less);
898+
EXPECT_EQ(neg_full_range <=> -full_range, std::strong_ordering::equal);
899+
#endif // __cpp_impl_three_way_comparison
860900
}
861901

862902
TEST(Duration, RelationalOperators) {
@@ -880,6 +920,27 @@ TEST(Duration, RelationalOperators) {
880920
#undef TEST_REL_OPS
881921
}
882922

923+
924+
#ifdef __cpp_impl_three_way_comparison
925+
926+
TEST(Duration, SpaceshipOperators) {
927+
#define TEST_REL_OPS(UNIT) \
928+
static_assert(UNIT(2) <=> UNIT(2) == std::strong_ordering::equal, ""); \
929+
static_assert(UNIT(1) <=> UNIT(2) == std::strong_ordering::less, ""); \
930+
static_assert(UNIT(3) <=> UNIT(2) == std::strong_ordering::greater, "");
931+
932+
TEST_REL_OPS(absl::Nanoseconds);
933+
TEST_REL_OPS(absl::Microseconds);
934+
TEST_REL_OPS(absl::Milliseconds);
935+
TEST_REL_OPS(absl::Seconds);
936+
TEST_REL_OPS(absl::Minutes);
937+
TEST_REL_OPS(absl::Hours);
938+
939+
#undef TEST_REL_OPS
940+
}
941+
942+
#endif // __cpp_impl_three_way_comparison
943+
883944
TEST(Duration, Addition) {
884945
#define TEST_ADD_OPS(UNIT) \
885946
do { \

absl/time/time.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,22 @@
7575
struct timeval;
7676
#endif
7777
#include <chrono> // NOLINT(build/c++11)
78+
79+
#ifdef __cpp_impl_three_way_comparison
80+
#include <compare>
81+
#endif // __cpp_impl_three_way_comparison
82+
7883
#include <cmath>
7984
#include <cstdint>
8085
#include <ctime>
8186
#include <limits>
8287
#include <ostream>
88+
#include <ratio> // NOLINT(build/c++11)
8389
#include <string>
8490
#include <type_traits>
8591
#include <utility>
8692

93+
#include "absl/base/attributes.h"
8794
#include "absl/base/config.h"
8895
#include "absl/base/macros.h"
8996
#include "absl/strings/string_view.h"
@@ -305,6 +312,14 @@ class Duration {
305312
};
306313

307314
// Relational Operators
315+
316+
#ifdef __cpp_impl_three_way_comparison
317+
318+
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
319+
Duration lhs, Duration rhs);
320+
321+
#endif // __cpp_impl_three_way_comparison
322+
308323
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
309324
Duration rhs);
310325
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs,
@@ -837,6 +852,11 @@ class Time {
837852
private:
838853
friend constexpr Time time_internal::FromUnixDuration(Duration d);
839854
friend constexpr Duration time_internal::ToUnixDuration(Time t);
855+
856+
#ifdef __cpp_impl_three_way_comparison
857+
friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs);
858+
#endif // __cpp_impl_three_way_comparison
859+
840860
friend constexpr bool operator<(Time lhs, Time rhs);
841861
friend constexpr bool operator==(Time lhs, Time rhs);
842862
friend Duration operator-(Time lhs, Time rhs);
@@ -848,6 +868,15 @@ class Time {
848868
};
849869

850870
// Relational Operators
871+
#ifdef __cpp_impl_three_way_comparison
872+
873+
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
874+
Time lhs, Time rhs) {
875+
return lhs.rep_ <=> rhs.rep_;
876+
}
877+
878+
#endif // __cpp_impl_three_way_comparison
879+
851880
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
852881
return lhs.rep_ < rhs.rep_;
853882
}
@@ -1723,6 +1752,25 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
17231752
: time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
17241753
}
17251754

1755+
1756+
#ifdef __cpp_impl_three_way_comparison
1757+
1758+
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
1759+
Duration lhs, Duration rhs) {
1760+
const int64_t lhs_hi = time_internal::GetRepHi(lhs);
1761+
const int64_t rhs_hi = time_internal::GetRepHi(rhs);
1762+
if (auto c = lhs_hi <=> rhs_hi; c != std::strong_ordering::equal) {
1763+
return c;
1764+
}
1765+
const uint32_t lhs_lo = time_internal::GetRepLo(lhs);
1766+
const uint32_t rhs_lo = time_internal::GetRepLo(rhs);
1767+
return (lhs_hi == (std::numeric_limits<int64_t>::min)())
1768+
? (lhs_lo + 1) <=> (rhs_lo + 1)
1769+
: lhs_lo <=> rhs_lo;
1770+
}
1771+
1772+
#endif // __cpp_impl_three_way_comparison
1773+
17261774
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
17271775
Duration rhs) {
17281776
return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) &&

absl/time/time_test.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
#endif
2525

2626
#include <chrono> // NOLINT(build/c++11)
27+
28+
#ifdef __cpp_impl_three_way_comparison
29+
#include <compare>
30+
#endif // __cpp_impl_three_way_comparison
31+
2732
#include <cstring>
2833
#include <ctime>
2934
#include <iomanip>
@@ -207,6 +212,22 @@ TEST(Time, RelationalOperators) {
207212
static_assert(t3 >= t2, "");
208213
static_assert(t1 >= t1, "");
209214
static_assert(t3 >= t1, "");
215+
216+
#ifdef __cpp_impl_three_way_comparison
217+
218+
static_assert((t1 <=> t1) == std::strong_ordering::equal, "");
219+
static_assert((t2 <=> t2) == std::strong_ordering::equal, "");
220+
static_assert((t3 <=> t3) == std::strong_ordering::equal, "");
221+
222+
static_assert((t1 <=> t2) == std::strong_ordering::less, "");
223+
static_assert((t2 <=> t3) == std::strong_ordering::less, "");
224+
static_assert((t1 <=> t3) == std::strong_ordering::less, "");
225+
226+
static_assert((t2 <=> t1) == std::strong_ordering::greater, "");
227+
static_assert((t3 <=> t2) == std::strong_ordering::greater, "");
228+
static_assert((t3 <=> t1) == std::strong_ordering::greater, "");
229+
230+
#endif // __cpp_impl_three_way_comparison
210231
}
211232

212233
TEST(Time, Infinity) {
@@ -218,6 +239,15 @@ TEST(Time, Infinity) {
218239
static_assert(ipast < ifuture, "");
219240
static_assert(ifuture > ipast, "");
220241

242+
#ifdef __cpp_impl_three_way_comparison
243+
244+
static_assert((ifuture <=> ifuture) == std::strong_ordering::equal, "");
245+
static_assert((ipast <=> ipast) == std::strong_ordering::equal, "");
246+
static_assert((ipast <=> ifuture) == std::strong_ordering::less, "");
247+
static_assert((ifuture <=> ipast) == std::strong_ordering::greater, "");
248+
249+
#endif // __cpp_impl_three_way_comparison
250+
221251
// Arithmetic saturates
222252
EXPECT_EQ(ifuture, ifuture + absl::Seconds(1));
223253
EXPECT_EQ(ifuture, ifuture - absl::Seconds(1));
@@ -233,6 +263,15 @@ TEST(Time, Infinity) {
233263
static_assert(t < ifuture, "");
234264
static_assert(t > ipast, "");
235265

266+
#ifdef __cpp_impl_three_way_comparison
267+
268+
static_assert((t <=> ifuture) == std::strong_ordering::less, "");
269+
static_assert((t <=> ipast) == std::strong_ordering::greater, "");
270+
static_assert((ipast <=> t) == std::strong_ordering::less, "");
271+
static_assert((ifuture <=> t) == std::strong_ordering::greater, "");
272+
273+
#endif // __cpp_impl_three_way_comparison
274+
236275
EXPECT_EQ(ifuture, t + absl::InfiniteDuration());
237276
EXPECT_EQ(ipast, t - absl::InfiniteDuration());
238277
}

0 commit comments

Comments
 (0)