From 83542e47644eb32a738b288a9de6540cbda0b8c9 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sat, 18 Mar 2023 12:54:17 +0200 Subject: [PATCH] [libc++][spaceship] Implement `operator<=>` for `duration` Implements parts of [[ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html | P1614R2 ]] Implemented `operator<=>` for `std::chrono::duration` Reviewed By: #libc, Mordante Differential Revision: https://reviews.llvm.org/D145881 --- libcxx/docs/Status/SpaceshipProjects.csv | 2 +- libcxx/include/__chrono/duration.h | 20 +++++ libcxx/include/chrono | 6 +- .../compare.three_way.pass.cpp | 77 +++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/std/time/time.duration/time.duration.comparisons/compare.three_way.pass.cpp diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv index a3dc4ee81ec3..e92fd1236a29 100644 --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -52,7 +52,7 @@ Section,Description,Dependencies,Assignee,Complete | `[range.iota.iterator] `_,| `ranges::iota_view::iterator `_,[concepts.cmp],Arthur O'Dwyer,|Complete| | `[range.transform.iterator] `_,| `ranges::transform_view::iterator `_,[concepts.cmp],Arthur O'Dwyer,|Complete| | `[range.elements.iterator] `_,| ranges::elements_view::iterator,[concepts.cmp],Hui Xie,|Complete| -| `[time.duration.comparisons] `_, "chrono::duration", None, Mark de Wever, |Not Started| +| `[time.duration.comparisons] `_, `chrono::duration `_, None, Hristo Hristov, |Complete| | `[time.point.comparisons] `_, "chrono::time_point", None, Mark de Wever, |Not Started| "| `[time.cal.day.nonmembers] `_ | `[time.cal.month.nonmembers] `_ diff --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h index 5b27a5493d71..2c8d50a99786 100644 --- a/libcxx/include/__chrono/duration.h +++ b/libcxx/include/__chrono/duration.h @@ -10,6 +10,8 @@ #ifndef _LIBCPP___CHRONO_DURATION_H #define _LIBCPP___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> @@ -343,6 +345,8 @@ operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return __duration_eq, duration<_Rep2, _Period2> >()(__lhs, __rhs); } +#if _LIBCPP_STD_VER <= 17 + // Duration != template @@ -354,6 +358,8 @@ operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // Duration < template @@ -417,6 +423,20 @@ operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs < __rhs); } +#if _LIBCPP_STD_VER >= 20 + +template + requires three_way_comparable> +_LIBCPP_HIDE_FROM_ABI +constexpr auto operator<=>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) +{ + using _Ct = common_type_t, duration<_Rep2, _Period2>>; + return _Ct(__lhs).count() <=> _Ct(__rhs).count(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // Duration + template diff --git a/libcxx/include/chrono b/libcxx/include/chrono index 7593e947ed62..f34fc590831a 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -182,7 +182,7 @@ template bool operator==(const duration& lhs, const duration& rhs); template constexpr - bool operator!=(const duration& lhs, const duration& rhs); + bool operator!=(const duration& lhs, const duration& rhs); // removed in C++20 template constexpr bool operator< (const duration& lhs, const duration& rhs); @@ -195,6 +195,10 @@ template template constexpr bool operator>=(const duration& lhs, const duration& rhs); +template + requires three_way_comparable + constexpr auto operator<=>(const duration& lhs, + const duration& rhs); // since C++20 // duration_cast template diff --git a/libcxx/test/std/time/time.duration/time.duration.comparisons/compare.three_way.pass.cpp b/libcxx/test/std/time/time.duration/time.duration.comparisons/compare.three_way.pass.cpp new file mode 100644 index 000000000000..282df3e786dc --- /dev/null +++ b/libcxx/test/std/time/time.duration/time.duration.comparisons/compare.three_way.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// duration + +// template +// requires ThreeWayComparable +// constexpr auto operator<=>(const duration& lhs, +// const duration& rhs); + +#include +#include +#include + +#include "test_comparisons.h" + +constexpr bool test() { + { + std::chrono::seconds s1(3); + std::chrono::seconds s2(3); + assert((s1 <=> s2) == std::strong_ordering::equal); + assert(testOrder(s1, s2, std::strong_ordering::equal)); + } + { + std::chrono::seconds s1(3); + std::chrono::seconds s2(4); + assert((s1 <=> s2) == std::strong_ordering::less); + assert(testOrder(s1, s2, std::strong_ordering::less)); + } + { + std::chrono::milliseconds s1(3); + std::chrono::microseconds s2(3000); + assert((s1 <=> s2) == std::strong_ordering::equal); + assert(testOrder(s1, s2, std::strong_ordering::equal)); + } + { + std::chrono::milliseconds s1(3); + std::chrono::microseconds s2(4000); + assert((s1 <=> s2) == std::strong_ordering::less); + assert(testOrder(s1, s2, std::strong_ordering::less)); + } + { + std::chrono::duration> s1(9); + std::chrono::duration> s2(10); + assert((s1 <=> s2) == std::strong_ordering::equal); + assert(testOrder(s1, s2, std::strong_ordering::equal)); + } + { + std::chrono::duration> s1(10); + std::chrono::duration> s2(9); + assert((s1 <=> s2) == std::strong_ordering::greater); + assert(testOrder(s1, s2, std::strong_ordering::greater)); + } + { + std::chrono::duration> s1(9); + std::chrono::duration> s2(10.1); + assert((s1 <=> s2) == std::strong_ordering::less); + assert(testOrder(s1, s2, std::strong_ordering::less)); + } + + return true; +} + +int main(int, char**) { + assert(test()); + static_assert(test()); + return 0; +}