Skip to content

Commit bd7ca12

Browse files
more strict checks
1 parent 11329c1 commit bd7ca12

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

libcxx/include/__chrono/is_clock.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include <__config>
1414
#include <__type_traits/integral_constant.h>
15+
#include <__type_traits/is_arithmetic.h>
16+
#include <__type_traits/is_same.h>
1517

1618
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1719
# pragma GCC system_header
@@ -23,14 +25,40 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2325

2426
namespace chrono {
2527

28+
template <class _Rep, class _Period>
29+
class duration;
30+
31+
template <class _Clock, class _Duration>
32+
class time_point;
33+
34+
template <class _TimePoint, class _Clock>
35+
constexpr bool __is_valid_clock_time_point_v = false;
36+
37+
template <class _Clock, class _Duration, class _ClockType>
38+
constexpr bool __is_valid_clock_time_point_v<time_point<_Clock, _Duration>, _ClockType> =
39+
_IsSame<time_point<_Clock, _Duration>, time_point<_ClockType>>::value ||
40+
_IsSame<_Duration, typename _ClockType::duration>::value;
41+
42+
// Check if a clock satisfies the Cpp17Clock requirements as defined in [time.clock.req]
2643
template <class _Tp>
2744
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_clock_v = requires {
2845
typename _Tp::rep;
46+
requires is_arithmetic_v<typename _Tp::rep>;
47+
2948
typename _Tp::period;
49+
requires __is_ratio_v<typename _Tp::period>;
50+
3051
typename _Tp::duration;
52+
requires _IsSame<typename _Tp::duration, duration<typename _Tp::rep, typename _Tp::period>>::value;
53+
3154
typename _Tp::time_point;
55+
requires __is_valid_clock_time_point_v<typename _Tp::time_point, _Tp>;
56+
3257
_Tp::is_steady;
58+
requires _IsSame<decltype(_Tp::is_steady), const bool>::value;
59+
3360
_Tp::now();
61+
requires _IsSame<decltype(_Tp::now()), typename _Tp::time_point>::value;
3462
};
3563

3664
template <class _Tp>

libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,102 @@ struct ValidSteadyClock {
7272
};
7373

7474
struct ValidSystemClock {
75-
using rep = int64_t;
75+
using rep = long long;
7676
using period = std::micro;
7777
using duration = std::chrono::microseconds;
7878
using time_point = std::chrono::time_point<ValidSystemClock>;
7979
static constexpr bool is_steady = false;
8080
static time_point now();
8181
};
8282

83+
// Test clocks with invalid is_steady type
84+
struct WrongIsSteadyType {
85+
using rep = long;
86+
using period = std::ratio<1>;
87+
using duration = std::chrono::seconds;
88+
using time_point = std::chrono::time_point<WrongIsSteadyType>;
89+
static bool is_steady; // Not const bool
90+
static time_point now();
91+
};
92+
93+
struct WrongIsSteadyNonBool {
94+
using rep = long;
95+
using period = std::ratio<1>;
96+
using duration = std::chrono::seconds;
97+
using time_point = std::chrono::time_point<WrongIsSteadyNonBool>;
98+
static constexpr int is_steady = 1; // Not bool
99+
static time_point now();
100+
};
101+
102+
// Test clocks with invalid now() return type
103+
struct WrongNowReturnType {
104+
using rep = long;
105+
using period = std::ratio<1>;
106+
using duration = std::chrono::seconds;
107+
using time_point = std::chrono::time_point<WrongNowReturnType>;
108+
static constexpr bool is_steady = false;
109+
static int now(); // Wrong return type
110+
};
111+
112+
// Test clocks with invalid period type
113+
struct WrongPeriodType {
114+
using rep = long;
115+
using period = int; // Not a ratio
116+
using duration = std::chrono::seconds;
117+
using time_point = std::chrono::time_point<WrongPeriodType>;
118+
static constexpr bool is_steady = false;
119+
static time_point now();
120+
};
121+
122+
// Test clocks with invalid rep type (neither arithmetic nor numeric_limits specialized)
123+
struct InvalidRepType {
124+
using rep = EmptyStruct; // Not arithmetic, no numeric_limits specialization
125+
using period = std::ratio<1>;
126+
using duration = std::chrono::duration<EmptyStruct>;
127+
using time_point = std::chrono::time_point<InvalidRepType, duration>;
128+
static constexpr bool is_steady = false;
129+
static time_point now();
130+
};
131+
132+
// Test clocks with wrong duration type
133+
struct WrongDurationType {
134+
using rep = long;
135+
using period = std::ratio<1>;
136+
using duration = std::chrono::milliseconds; // Should be duration<long, ratio<1>>
137+
using time_point = std::chrono::time_point<WrongDurationType>;
138+
static constexpr bool is_steady = false;
139+
static time_point now();
140+
};
141+
142+
// Test clocks with wrong time_point type
143+
struct WrongTimePointType {
144+
using rep = long;
145+
using period = std::ratio<1>;
146+
using duration = std::chrono::duration<long, std::ratio<1>>;
147+
using time_point = int; // Not a time_point
148+
static constexpr bool is_steady = false;
149+
static time_point now();
150+
};
151+
152+
struct WrongTimePointClock {
153+
using rep = long;
154+
using period = std::ratio<1>;
155+
using duration = std::chrono::duration<long, std::ratio<1>>;
156+
using time_point = std::chrono::time_point<ValidSystemClock>; // Wrong clock type
157+
static constexpr bool is_steady = false;
158+
static time_point now();
159+
};
160+
161+
// Valid clock with time_point that has matching duration instead of matching clock
162+
struct ValidClockWithDurationMatch {
163+
using rep = int;
164+
using period = std::milli;
165+
using duration = std::chrono::duration<int, std::milli>;
166+
using time_point = std::chrono::time_point<ValidSystemClock, duration>; // Valid: matches duration
167+
static constexpr bool is_steady = false;
168+
static time_point now();
169+
};
170+
83171
int main(int, char**) {
84172
// Test both is_clock and is_clock_v
85173
static_assert(std::chrono::is_clock<std::chrono::system_clock>::value);
@@ -114,6 +202,27 @@ int main(int, char**) {
114202
// Test valid custom clocks
115203
static_assert(std::chrono::is_clock_v<ValidSteadyClock>);
116204
static_assert(std::chrono::is_clock_v<ValidSystemClock>);
205+
static_assert(std::chrono::is_clock_v<ValidClockWithDurationMatch>);
206+
207+
// Test clocks with invalid is_steady type
208+
static_assert(!std::chrono::is_clock_v<WrongIsSteadyType>); // is_steady not const bool
209+
static_assert(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type
210+
211+
// Test clocks with invalid now() return type
212+
static_assert(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point
213+
214+
// Test clocks with invalid period type
215+
static_assert(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio
216+
217+
// Test clocks with invalid rep type
218+
static_assert(!std::chrono::is_clock_v<InvalidRepType>); // rep is not arithmetic and no numeric_limits
219+
220+
// Test clocks with wrong duration type
221+
static_assert(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period>
222+
223+
// Test clocks with wrong time_point type
224+
static_assert(!std::chrono::is_clock_v<WrongTimePointType>); // time_point is not a time_point
225+
static_assert(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration
117226

118227
// cv-qualified and reference types
119228
static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>);

0 commit comments

Comments
 (0)