Skip to content

Commit 83542e4

Browse files
committed
[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
1 parent 32baf5c commit 83542e4

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

libcxx/docs/Status/SpaceshipProjects.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Section,Description,Dependencies,Assignee,Complete
5252
| `[range.iota.iterator] <https://wg21.link/range.iota.iterator>`_,| `ranges::iota_view::iterator <https://reviews.llvm.org/D110774>`_,[concepts.cmp],Arthur O'Dwyer,|Complete|
5353
| `[range.transform.iterator] <https://wg21.link/range.transform.iterator>`_,| `ranges::transform_view::iterator <https://reviews.llvm.org/D110774>`_,[concepts.cmp],Arthur O'Dwyer,|Complete|
5454
| `[range.elements.iterator] <https://wg21.link/range.elements.iterator>`_,| ranges::elements_view::iterator,[concepts.cmp],Hui Xie,|Complete|
55-
| `[time.duration.comparisons] <https://wg21.link/time.duration.comparisons>`_, "chrono::duration", None, Mark de Wever, |Not Started|
55+
| `[time.duration.comparisons] <https://wg21.link/time.duration.comparisons>`_, `chrono::duration <https://reviews.llvm.org/D145881>`_, None, Hristo Hristov, |Complete|
5656
| `[time.point.comparisons] <https://wg21.link/time.point.comparisons>`_, "chrono::time_point", None, Mark de Wever, |Not Started|
5757
"| `[time.cal.day.nonmembers] <https://wg21.link/time.cal.day.nonmembers>`_
5858
| `[time.cal.month.nonmembers] <https://wg21.link/time.cal.month.nonmembers>`_

libcxx/include/__chrono/duration.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#ifndef _LIBCPP___CHRONO_DURATION_H
1111
#define _LIBCPP___CHRONO_DURATION_H
1212

13+
#include <__compare/ordering.h>
14+
#include <__compare/three_way_comparable.h>
1315
#include <__config>
1416
#include <__type_traits/common_type.h>
1517
#include <__type_traits/enable_if.h>
@@ -343,6 +345,8 @@ operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period
343345
return __duration_eq<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >()(__lhs, __rhs);
344346
}
345347

348+
#if _LIBCPP_STD_VER <= 17
349+
346350
// Duration !=
347351

348352
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
@@ -354,6 +358,8 @@ operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period
354358
return !(__lhs == __rhs);
355359
}
356360

361+
#endif // _LIBCPP_STD_VER <= 17
362+
357363
// Duration <
358364

359365
template <class _LhsDuration, class _RhsDuration>
@@ -417,6 +423,20 @@ operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period
417423
return !(__lhs < __rhs);
418424
}
419425

426+
#if _LIBCPP_STD_VER >= 20
427+
428+
template<class _Rep1, class _Period1, class _Rep2, class _Period2>
429+
requires three_way_comparable<common_type_t<_Rep1, _Rep2>>
430+
_LIBCPP_HIDE_FROM_ABI
431+
constexpr auto operator<=>(const duration<_Rep1, _Period1>& __lhs,
432+
const duration<_Rep2, _Period2>& __rhs)
433+
{
434+
using _Ct = common_type_t<duration<_Rep1, _Period1>, duration<_Rep2, _Period2>>;
435+
return _Ct(__lhs).count() <=> _Ct(__rhs).count();
436+
}
437+
438+
#endif // _LIBCPP_STD_VER >= 20
439+
420440
// Duration +
421441

422442
template <class _Rep1, class _Period1, class _Rep2, class _Period2>

libcxx/include/chrono

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ template <class Rep1, class Period1, class Rep2, class Period2>
182182
bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
183183
template <class Rep1, class Period1, class Rep2, class Period2>
184184
constexpr
185-
bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
185+
bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // removed in C++20
186186
template <class Rep1, class Period1, class Rep2, class Period2>
187187
constexpr
188188
bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
@@ -195,6 +195,10 @@ template <class Rep1, class Period1, class Rep2, class Period2>
195195
template <class Rep1, class Period1, class Rep2, class Period2>
196196
constexpr
197197
bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
198+
template<class Rep1, class Period1, class Rep2, class Period2>
199+
requires three_way_comparable<typename CT::rep>
200+
constexpr auto operator<=>(const duration<Rep1, Period1>& lhs,
201+
const duration<Rep2, Period2>& rhs); // since C++20
198202
199203
// duration_cast
200204
template <class ToDuration, class Rep, class Period>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <chrono>
12+
13+
// duration
14+
15+
// template<class Rep1, class Period1, class Rep2, class Period2>
16+
// requires ThreeWayComparable<typename CT::rep>
17+
// constexpr auto operator<=>(const duration<Rep1, Period1>& lhs,
18+
// const duration<Rep2, Period2>& rhs);
19+
20+
#include <cassert>
21+
#include <chrono>
22+
#include <ratio>
23+
24+
#include "test_comparisons.h"
25+
26+
constexpr bool test() {
27+
{
28+
std::chrono::seconds s1(3);
29+
std::chrono::seconds s2(3);
30+
assert((s1 <=> s2) == std::strong_ordering::equal);
31+
assert(testOrder(s1, s2, std::strong_ordering::equal));
32+
}
33+
{
34+
std::chrono::seconds s1(3);
35+
std::chrono::seconds s2(4);
36+
assert((s1 <=> s2) == std::strong_ordering::less);
37+
assert(testOrder(s1, s2, std::strong_ordering::less));
38+
}
39+
{
40+
std::chrono::milliseconds s1(3);
41+
std::chrono::microseconds s2(3000);
42+
assert((s1 <=> s2) == std::strong_ordering::equal);
43+
assert(testOrder(s1, s2, std::strong_ordering::equal));
44+
}
45+
{
46+
std::chrono::milliseconds s1(3);
47+
std::chrono::microseconds s2(4000);
48+
assert((s1 <=> s2) == std::strong_ordering::less);
49+
assert(testOrder(s1, s2, std::strong_ordering::less));
50+
}
51+
{
52+
std::chrono::duration<int, std::ratio<2, 3>> s1(9);
53+
std::chrono::duration<int, std::ratio<3, 5>> s2(10);
54+
assert((s1 <=> s2) == std::strong_ordering::equal);
55+
assert(testOrder(s1, s2, std::strong_ordering::equal));
56+
}
57+
{
58+
std::chrono::duration<int, std::ratio<2, 3>> s1(10);
59+
std::chrono::duration<int, std::ratio<3, 5>> s2(9);
60+
assert((s1 <=> s2) == std::strong_ordering::greater);
61+
assert(testOrder(s1, s2, std::strong_ordering::greater));
62+
}
63+
{
64+
std::chrono::duration<int, std::ratio<2, 3>> s1(9);
65+
std::chrono::duration<double, std::ratio<3, 5>> s2(10.1);
66+
assert((s1 <=> s2) == std::strong_ordering::less);
67+
assert(testOrder(s1, s2, std::strong_ordering::less));
68+
}
69+
70+
return true;
71+
}
72+
73+
int main(int, char**) {
74+
assert(test());
75+
static_assert(test());
76+
return 0;
77+
}

0 commit comments

Comments
 (0)