summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuxuan Chen <ych@meta.com>2025-09-25 12:02:39 -0700
committerYuxuan Chen <ych@meta.com>2025-09-25 14:16:42 -0700
commit8a6adc0a8669719f275a4ff98d3688f6089dbe02 (patch)
tree7de7ae9f63729dd251018dd0c199d51a93923d2d
parent11329c13affdf825e68735ffaca67d462fbef585 (diff)
-rw-r--r--libcxx/include/__chrono/is_clock.h27
-rw-r--r--libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp111
2 files changed, 137 insertions, 1 deletions
diff --git a/libcxx/include/__chrono/is_clock.h b/libcxx/include/__chrono/is_clock.h
index da65788af8a3..75626628309e 100644
--- a/libcxx/include/__chrono/is_clock.h
+++ b/libcxx/include/__chrono/is_clock.h
@@ -12,6 +12,8 @@
#include <__config>
#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/is_same.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -23,14 +25,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace chrono {
+template <class _Rep, class _Period>
+class duration;
+
+template <class _Clock, class _Duration>
+class time_point;
+
+template <class _TimePoint, class _Clock>
+constexpr bool __is_valid_clock_time_point_v = false;
+
+template <class _Clock, class _Duration, class _ClockType>
+constexpr bool __is_valid_clock_time_point_v<time_point<_Clock, _Duration>, _ClockType> =
+ _IsSame<_Clock, _ClockType>::value || _IsSame<_Duration, typename _ClockType::duration>::value;
+
+// Check if a clock satisfies the Cpp17Clock requirements as defined in [time.clock.req]
template <class _Tp>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_clock_v = requires {
typename _Tp::rep;
+ requires is_arithmetic_v<typename _Tp::rep>;
+
typename _Tp::period;
+ requires __is_ratio_v<typename _Tp::period>;
+
typename _Tp::duration;
+ requires _IsSame<typename _Tp::duration, duration<typename _Tp::rep, typename _Tp::period>>::value;
+
typename _Tp::time_point;
+ requires __is_valid_clock_time_point_v<typename _Tp::time_point, _Tp>;
+
_Tp::is_steady;
+ requires _IsSame<decltype(_Tp::is_steady), const bool>::value;
+
_Tp::now();
+ requires _IsSame<decltype(_Tp::now()), typename _Tp::time_point>::value;
};
template <class _Tp>
diff --git a/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp
index 78473808a00e..f6e73bd288d0 100644
--- a/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp
+++ b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp
@@ -72,7 +72,7 @@ struct ValidSteadyClock {
};
struct ValidSystemClock {
- using rep = int64_t;
+ using rep = long long;
using period = std::micro;
using duration = std::chrono::microseconds;
using time_point = std::chrono::time_point<ValidSystemClock>;
@@ -80,6 +80,94 @@ struct ValidSystemClock {
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 invalid rep type (neither arithmetic nor numeric_limits specialized)
+struct InvalidRepType {
+ using rep = EmptyStruct; // Not arithmetic, no numeric_limits specialization
+ using period = std::ratio<1>;
+ using duration = std::chrono::duration<EmptyStruct>;
+ using time_point = std::chrono::time_point<InvalidRepType, duration>;
+ 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();
+};
+
int main(int, char**) {
// Test both is_clock and is_clock_v
static_assert(std::chrono::is_clock<std::chrono::system_clock>::value);
@@ -114,6 +202,27 @@ int main(int, char**) {
// 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>);
+
+ // Test clocks with invalid is_steady type
+ static_assert(!std::chrono::is_clock_v<WrongIsSteadyType>); // is_steady not const bool
+ static_assert(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type
+
+ // Test clocks with invalid now() return type
+ static_assert(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point
+
+ // Test clocks with invalid period type
+ static_assert(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio
+
+ // Test clocks with invalid rep type
+ static_assert(!std::chrono::is_clock_v<InvalidRepType>); // rep is not arithmetic and no numeric_limits
+
+ // Test clocks with wrong duration type
+ static_assert(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period>
+
+ // Test clocks with wrong time_point type
+ static_assert(!std::chrono::is_clock_v<WrongTimePointType>); // time_point is not a time_point
+ static_assert(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration
// cv-qualified and reference types
static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>);