aboutsummaryrefslogtreecommitdiff
path: root/libcxx/test/std/time/time.traits/is.clock.compile.pass.cpp
blob: 4af29d20943ea77e78c3f245fdf7ee727b293f4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// REQUIRES: std-at-least-c++20

// <chrono>
//
// template<class T> struct is_clock;
// template<class T> constexpr bool is_clock_v = is_clock<T>::value;

#include <chrono>
#include <ratio>

#include "test_macros.h"

struct EmptyStruct {};

// Test structs missing required members
struct MissingRep {
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::seconds;
  using time_point                = std::chrono::time_point<MissingRep>;
  static constexpr bool is_steady = false;
  static time_point now();
};

struct MissingPeriod {
  using rep                       = long;
  using duration                  = std::chrono::seconds;
  using time_point                = std::chrono::time_point<MissingPeriod>;
  static constexpr bool is_steady = false;
  static time_point now();
};

struct MissingDuration {
  using rep                       = long;
  using time_point                = long;
  static constexpr bool is_steady = false;
  static time_point now();
};

struct MissingTimePoint {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::seconds;
  static constexpr bool is_steady = false;
  static std::chrono::time_point<MissingTimePoint> now();
};

struct MissingIsSteady {
  using rep        = long;
  using period     = std::ratio<1>;
  using duration   = std::chrono::seconds;
  using time_point = std::chrono::time_point<MissingIsSteady>;
  static time_point now();
};

struct MissingNow {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::seconds;
  using time_point                = std::chrono::time_point<MissingNow>;
  static constexpr bool is_steady = false;
};

// Valid clock types
struct ValidSteadyClock {
  using rep                       = long long;
  using period                    = std::nano;
  using duration                  = std::chrono::nanoseconds;
  using time_point                = std::chrono::time_point<ValidSteadyClock>;
  static constexpr bool is_steady = true;
  static time_point now();
};

struct ValidSystemClock {
  using rep                       = long long;
  using period                    = std::micro;
  using duration                  = std::chrono::microseconds;
  using time_point                = std::chrono::time_point<ValidSystemClock>;
  static constexpr bool is_steady = false;
  static time_point now();
};

// Test clocks with invalid is_steady type
struct WrongIsSteadyType {
  using rep        = long;
  using period     = std::ratio<1>;
  using duration   = std::chrono::seconds;
  using time_point = std::chrono::time_point<WrongIsSteadyType>;
  static bool is_steady; // Not const bool
  static time_point now();
};

struct WrongIsSteadyNonBool {
  using rep                      = long;
  using period                   = std::ratio<1>;
  using duration                 = std::chrono::seconds;
  using time_point               = std::chrono::time_point<WrongIsSteadyNonBool>;
  static constexpr int is_steady = 1; // Not bool
  static time_point now();
};

// Test clocks with invalid now() return type
struct WrongNowReturnType {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::seconds;
  using time_point                = std::chrono::time_point<WrongNowReturnType>;
  static constexpr bool is_steady = false;
  static int now(); // Wrong return type
};

// Test clocks with invalid period type
struct WrongPeriodType {
  using rep                       = long;
  using period                    = int; // Not a ratio
  using duration                  = std::chrono::seconds;
  using time_point                = std::chrono::time_point<WrongPeriodType>;
  static constexpr bool is_steady = false;
  static time_point now();
};

// Test clocks with wrong duration type
struct WrongDurationType {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::milliseconds; // Should be duration<long, ratio<1>>
  using time_point                = std::chrono::time_point<WrongDurationType>;
  static constexpr bool is_steady = false;
  static time_point now();
};

// Test clocks with wrong time_point type
struct WrongTimePointType {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::duration<long, std::ratio<1>>;
  using time_point                = int; // Not a time_point
  static constexpr bool is_steady = false;
  static time_point now();
};

struct WrongTimePointClock {
  using rep                       = long;
  using period                    = std::ratio<1>;
  using duration                  = std::chrono::duration<long, std::ratio<1>>;
  using time_point                = std::chrono::time_point<ValidSystemClock>; // Wrong clock type
  static constexpr bool is_steady = false;
  static time_point now();
};

// Valid clock with time_point that has matching duration instead of matching clock
struct ValidClockWithDurationMatch {
  using rep                       = int;
  using period                    = std::milli;
  using duration                  = std::chrono::duration<int, std::milli>;
  using time_point                = std::chrono::time_point<ValidSystemClock, duration>; // Valid: matches duration
  static constexpr bool is_steady = false;
  static time_point now();
};

// Test both is_clock and is_clock_v
static_assert(std::chrono::is_clock<std::chrono::system_clock>::value);
static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);

// Test standard clock types
static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<std::chrono::high_resolution_clock>);

// Test non-clock types
static_assert(!std::chrono::is_clock_v<EmptyStruct>);
static_assert(!std::chrono::is_clock_v<int>);
static_assert(!std::chrono::is_clock_v<void>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock::time_point>);
static_assert(!std::chrono::is_clock_v<std::chrono::seconds>);
static_assert(!std::chrono::is_clock_v<std::chrono::milliseconds>);

// Test structs missing required members
static_assert(!std::chrono::is_clock_v<MissingRep>);
static_assert(!std::chrono::is_clock_v<MissingPeriod>);
static_assert(!std::chrono::is_clock_v<MissingDuration>);
static_assert(!std::chrono::is_clock_v<MissingTimePoint>);
static_assert(!std::chrono::is_clock_v<MissingIsSteady>);
static_assert(!std::chrono::is_clock_v<MissingNow>);

// Test valid custom clocks
static_assert(std::chrono::is_clock_v<ValidSteadyClock>);
static_assert(std::chrono::is_clock_v<ValidSystemClock>);
static_assert(std::chrono::is_clock_v<ValidClockWithDurationMatch>);

// cv-qualified and reference types
static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<volatile std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<const volatile std::chrono::system_clock>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&&>);
static_assert(!std::chrono::is_clock_v<const std::chrono::system_clock&>);

// array and pointer types
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[]>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[10]>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock*>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock* const>);

// The Standard defined a minimum set of checks and allowed implementation to perform stricter checks. The following
// static asserts are implementation specific and a conforming standard library implementation doesn't have to produce
// the same outcome.

// Test clocks with invalid is_steady type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyType>);    // is_steady not const bool
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type

// Test clocks with invalid now() return type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point

// Test clocks with invalid period type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio

// Test clocks with wrong duration type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period>

// Test clocks with wrong time_point type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointType>);  // time_point is not a time_point
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration