diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -52,7 +52,7 @@ | `[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 --- 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 @@ return __duration_eq, duration<_Rep2, _Period2> >()(__lhs, __rhs); } +#if _LIBCPP_STD_VER <= 17 + // Duration != template @@ -354,6 +358,8 @@ return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // Duration < template @@ -417,6 +423,20 @@ 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 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -182,7 +182,7 @@ 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 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 --- /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; +}