[libcxx-commits] [libcxx] d94a770 - [libc++][spaceship] Implement `operator<=>` for `time_point`
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Apr 8 22:47:27 PDT 2023
Author: Hristo Hristov
Date: 2023-04-09T08:47:20+03:00
New Revision: d94a770f7b05161e0b8bc87975cfbc7f79d4b497
URL: https://github.com/llvm/llvm-project/commit/d94a770f7b05161e0b8bc87975cfbc7f79d4b497
DIFF: https://github.com/llvm/llvm-project/commit/d94a770f7b05161e0b8bc87975cfbc7f79d4b497.diff
LOG: [libc++][spaceship] Implement `operator<=>` for `time_point`
Depends on D145881
Implements parts of **P1614R2**: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html
Implements `operator<=>` for `time_point`
Reviewed By: #libc, Mordante
Differential Revision: https://reviews.llvm.org/D146250
Added:
libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.compile.fail.cpp
libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.pass.cpp
Modified:
libcxx/docs/Status/SpaceshipProjects.csv
libcxx/include/__chrono/time_point.h
libcxx/include/chrono
Removed:
################################################################################
diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index ab488ab847665..02eac2655d24c 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -53,7 +53,7 @@ Section,Description,Dependencies,Assignee,Complete
| `[range.transform.iterator] <https://wg21.link/range.transform.iterator>`_,| `ranges::transform_view::iterator <https://reviews.llvm.org/D110774>`_,[concepts.cmp],Arthur O'Dwyer,|Complete|
| `[range.elements.iterator] <https://wg21.link/range.elements.iterator>`_,| ranges::elements_view::iterator,[concepts.cmp],Hui Xie,|Complete|
| `[time.duration.comparisons] <https://wg21.link/time.duration.comparisons>`_, `chrono::duration <https://reviews.llvm.org/D145881>`_, None, Hristo Hristov, |Complete|
-| `[time.point.comparisons] <https://wg21.link/time.point.comparisons>`_, `chrono::time_point <https://reviews.llvm.org/D146250>`_, None, Hristo Hristov, |In Progress|
+| `[time.point.comparisons] <https://wg21.link/time.point.comparisons>`_, `chrono::time_point <https://reviews.llvm.org/D146250>`_, None, Hristo Hristov, |Complete|
"| `[time.cal.day.nonmembers] <https://wg21.link/time.cal.day.nonmembers>`_
| `[time.cal.month.nonmembers] <https://wg21.link/time.cal.month.nonmembers>`_
| `[time.cal.year.nonmembers] <https://wg21.link/time.cal.year.nonmembers>`_
diff --git a/libcxx/include/__chrono/time_point.h b/libcxx/include/__chrono/time_point.h
index 8ac3158d54637..c14835401fa40 100644
--- a/libcxx/include/__chrono/time_point.h
+++ b/libcxx/include/__chrono/time_point.h
@@ -11,6 +11,8 @@
#define _LIBCPP___CHRONO_TIME_POINT_H
#include <__chrono/duration.h>
+#include <__compare/ordering.h>
+#include <__compare/three_way_comparable.h>
#include <__config>
#include <__type_traits/common_type.h>
#include <__type_traits/enable_if.h>
@@ -150,6 +152,8 @@ operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock,
return __lhs.time_since_epoch() == __rhs.time_since_epoch();
}
+#if _LIBCPP_STD_VER <= 17
+
// time_point !=
template <class _Clock, class _Duration1, class _Duration2>
@@ -160,6 +164,8 @@ operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock,
return !(__lhs == __rhs);
}
+#endif // _LIBCPP_STD_VER <= 17
+
// time_point <
template <class _Clock, class _Duration1, class _Duration2>
@@ -200,6 +206,16 @@ operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock,
return !(__lhs < __rhs);
}
+#if _LIBCPP_STD_VER >= 20
+
+template <class _Clock, class _Duration1, three_way_comparable_with<_Duration1> _Duration2>
+_LIBCPP_HIDE_FROM_ABI constexpr auto
+operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
+ return __lhs.time_since_epoch() <=> __rhs.time_since_epoch();
+}
+
+#endif // _LIBCPP_STD_VER >= 20
+
// time_point operator+(time_point x, duration y);
template <class _Clock, class _Duration1, class _Rep2, class _Period2>
diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index a6b4565811f7b..b5d3b0318742a 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -235,7 +235,7 @@ template <class Clock, class Duration1, class Duration2>
template <class Clock, class Duration1, class Duration2>
bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
- bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
+ bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // removed in C++20
template <class Clock, class Duration1, class Duration2>
bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
@@ -244,6 +244,10 @@ template <class Clock, class Duration1, class Duration2>
bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
+template<class Clock, class Duration1,
+ three_way_comparable_with<Duration1> Duration2>
+ constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs,
+ const time_point<Clock, Duration2>& rhs); // since C++20
// time_point_cast (constexpr in C++14)
diff --git a/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.compile.fail.cpp b/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.compile.fail.cpp
new file mode 100644
index 0000000000000..9d4ab04c77e04
--- /dev/null
+++ b/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.compile.fail.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <chrono>
+
+// time_point
+
+// template<class Clock, class Duration1,
+// three_way_comparable_with<Duration1> Duration2>
+// constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs,
+// const time_point<Clock, Duration2>& rhs);
+
+// time_points with
diff erent clocks should not compare
+
+#include <chrono>
+
+#include "../../clock.h"
+
+int main(int, char**) {
+ using namespace std::chrono_literals;
+ std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> t1{3ms};
+ std::chrono::time_point<Clock, std::chrono::milliseconds> t2{3ms};
+
+ t1 <=> t2;
+
+ return 0;
+}
diff --git a/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.pass.cpp b/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.pass.cpp
new file mode 100644
index 0000000000000..aed80138303e9
--- /dev/null
+++ b/libcxx/test/std/time/time.point/time.point.comparisons/compare.three_way.pass.cpp
@@ -0,0 +1,127 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <chrono>
+
+// time_point
+
+// template<class Clock, class Duration1,
+// three_way_comparable_with<Duration1> Duration2>
+// constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs,
+// const time_point<Clock, Duration2>& rhs);
+
+#include <cassert>
+#include <chrono>
+#include <ratio>
+
+#include "test_comparisons.h"
+
+constexpr void test_with_integral_ticks_value() {
+ using Clock = std::chrono::system_clock;
+
+ using Duration1 = std::chrono::milliseconds;
+ using Duration2 = std::chrono::microseconds;
+ using T1 = std::chrono::time_point<Clock, Duration1>;
+ using T2 = std::chrono::time_point<Clock, Duration2>;
+
+ {
+ T1 t1(Duration1(3));
+ T1 t2(Duration1(3));
+ assert((t1 <=> t2) == std::strong_ordering::equal);
+ assert(testOrder(t1, t2, std::strong_ordering::equal));
+ }
+ {
+ T1 t1(Duration1(3));
+ T1 t2(Duration1(4));
+ assert((t1 <=> t2) == std::strong_ordering::less);
+ assert(testOrder(t1, t2, std::strong_ordering::less));
+ }
+ {
+ T1 t1(Duration1(3));
+ T2 t2(Duration2(3000));
+ assert((t1 <=> t2) == std::strong_ordering::equal);
+ assert(testOrder(t1, t2, std::strong_ordering::equal));
+ }
+ {
+ T1 t1(Duration1(3));
+ T2 t2(Duration2(3001));
+ assert((t1 <=> t2) == std::strong_ordering::less);
+ assert(testOrder(t1, t2, std::strong_ordering::less));
+ assert((t2 <=> t1) == std::strong_ordering::greater);
+ assert(testOrder(t2, t1, std::strong_ordering::greater));
+ }
+}
+
+constexpr void test_with_integral_ticks_value_and_custom_period_value() {
+ using Clock = std::chrono::system_clock;
+
+ using DInt30Hz = std::chrono::duration<int, std::ratio<1, 30>>;
+ using DInt60Hz = std::chrono::duration<int, std::ratio<1, 60>>;
+
+ using TIntR1 = std::chrono::time_point<Clock, DInt30Hz>;
+ using TIntR2 = std::chrono::time_point<Clock, DInt60Hz>;
+
+ {
+ TIntR1 t1(DInt30Hz(10));
+ TIntR2 t2(DInt60Hz(20));
+ assert((t1 <=> t2) == std::strong_ordering::equal);
+ assert(testOrder(t1, t2, std::strong_ordering::equal));
+ }
+ {
+ TIntR1 t1(DInt30Hz(10));
+ TIntR2 t2(DInt60Hz(21));
+ assert((t1 <=> t2) == std::strong_ordering::less);
+ assert(testOrder(t1, t2, std::strong_ordering::less));
+ }
+ {
+ TIntR1 t1(DInt30Hz(11));
+ TIntR2 t2(DInt60Hz(20));
+ assert((t1 <=> t2) == std::strong_ordering::greater);
+ assert(testOrder(t1, t2, std::strong_ordering::greater));
+ }
+}
+
+constexpr void test_with_floating_point_ticks_value() {
+ using Clock = std::chrono::system_clock;
+
+ using DF30Hz = std::chrono::duration<double, std::ratio<1, 30>>;
+ using DF60Hz = std::chrono::duration<double, std::ratio<1, 60>>;
+ using F1 = std::chrono::time_point<Clock, DF30Hz>;
+ using F2 = std::chrono::time_point<Clock, DF60Hz>;
+
+ // No equality comparison test for floating point values.
+
+ {
+ F1 t1(DF30Hz(3.5));
+ F2 t2(DF60Hz(7.1));
+ assert((t1 <=> t2) == std::weak_ordering::less);
+ assert(testOrder(t1, t2, std::weak_ordering::less));
+ }
+ {
+ F1 t1(DF30Hz(3.6));
+ F2 t2(DF60Hz(7.0));
+ assert((t1 <=> t2) == std::weak_ordering::greater);
+ assert(testOrder(t1, t2, std::weak_ordering::greater));
+ }
+}
+
+constexpr bool test() {
+ test_with_integral_ticks_value();
+ test_with_integral_ticks_value_and_custom_period_value();
+ test_with_floating_point_ticks_value();
+
+ return true;
+}
+
+int main(int, char**) {
+ assert(test());
+ static_assert(test());
+ return 0;
+}
More information about the libcxx-commits
mailing list