diff --git a/stl/inc/__msvc_chrono.hpp b/stl/inc/__msvc_chrono.hpp index 094f700699d..cdf2030242a 100644 --- a/stl/inc/__msvc_chrono.hpp +++ b/stl/inc/__msvc_chrono.hpp @@ -58,15 +58,32 @@ namespace chrono { } }; + _EXPORT_STD template > + class duration; + + _EXPORT_STD template + class time_point; + #if _HAS_CXX20 _EXPORT_STD template _NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr bool is_clock_v = requires { + // Basic checks from N5014 [time.traits.is.clock]/1 typename _Clock::rep; typename _Clock::period; typename _Clock::duration; typename _Clock::time_point; _Clock::is_steady; _Clock::now(); + + // Additional stricter checks from N5014 [time.clock.req]/2 + // "An arithmetic type or a class emulating an arithmetic type" is not checked + requires _Is_ratio_v; + requires same_as>; + requires same_as> + || same_as>; + { _Clock::is_steady } -> std::same_as; + { _Clock::now() } -> std::same_as; }; _EXPORT_STD template struct _NO_SPECIALIZATIONS_CITING("N5014 [time.traits.is.clock]/2") is_clock : bool_constant> {}; @@ -84,9 +101,6 @@ namespace chrono { true; #endif // ^^^ !_HAS_CXX20 ^^^ - _EXPORT_STD template > - class duration; - template constexpr bool _Is_duration_v = _Is_specialization_v<_Ty, duration>; @@ -203,7 +217,7 @@ namespace chrono { _Rep _MyRep; // the stored rep }; - _EXPORT_STD template + _EXPORT_STD template class time_point { // represents a point in time public: using clock = _Clock; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_clocks/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_clocks/test.cpp index 09cb4b1f4b2..8a2af4a0d1a 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_clocks/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_clocks/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -18,83 +19,289 @@ using namespace std; using namespace std::chrono; -struct not_a_clock { - bool rep(); - static char period; - int duration(); - static float time_point; - using is_steady = long; - static int now; +struct real_fake_clock { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct real_fake_clock { - using rep = bool; - using period = char; - using duration = float; - using time_point = int; - static long is_steady; - static short now(); +struct rep_missing { + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_rep { - using period = char; - using duration = float; - using time_point = int; - static long is_steady; - static short now(); +struct rep_not_type { + char rep; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_period { - using rep = bool; - using duration = float; - using time_point = int; - static long is_steady; - static short now(); +struct rep_wrong_type { + using rep = real_fake_clock; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_duration { - using rep = bool; - using period = char; - using time_point = int; - static long is_steady; - static short now(); +struct period_missing { + using rep = long long; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_time_point { - using rep = bool; - using period = char; - using duration = float; - static long is_steady; - static short now(); +struct period_not_type { + using rep = long long; + char period; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_steady { - using rep = bool; - using period = char; - using duration = float; - using time_point = int; - static short now(); +struct period_wrong_type { + using rep = long long; + using period = char; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -struct no_now { - using rep = bool; - using period = char; - using duration = float; - using time_point = int; - static long is_steady; +struct duration_missing { + using rep = long long; + using period = micro; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); }; -static_assert(is_clock::value, "steady_clock is not a clock"); -static_assert(is_clock_v, "steady_clock is not a clock"); -static_assert(is_clock_v, "real_fake_clock is not a clock"); -static_assert(!is_clock_v, "not_a_clock is a clock"); +struct duration_not_type { + using rep = long long; + using period = micro; + char duration; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; -static_assert(!is_clock_v, "no_rep is a clock"); -static_assert(!is_clock_v, "no_period is a clock"); -static_assert(!is_clock_v, "no_duration is a clock"); -static_assert(!is_clock_v, "no_time_point is a clock"); -static_assert(!is_clock_v, "no_steady is a clock"); -static_assert(!is_clock_v, "no_now is a clock"); +struct duration_wrong_type { + using rep = long long; + using period = micro; + using duration = int; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct duration_slightly_wrong_type { + using rep = long long; + using period = micro; + using duration = milliseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct duration_slightly_wrong_type2 { + using rep = long long; + using period = micro; + using duration = duration; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct time_point_missing { + using rep = long long; + using period = micro; + using duration = microseconds; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct time_point_not_type { + using rep = long long; + using period = micro; + using duration = microseconds; + char time_point; + static constexpr bool is_steady = false; + static chrono::time_point now(); +}; + +struct time_point_wrong_type { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = int; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct time_point_wrong_type2 { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct time_point_wrong_type3 { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct time_point_different_clock_ok { + using rep = long long; + using period = milli; + using duration = milliseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct is_steady_missing { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static time_point now(); +}; + +struct is_steady_type { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + using is_steady = bool; + static time_point now(); +}; + +struct is_steady_not_static { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + bool is_steady; + static time_point now(); +}; + +struct is_steady_wrong_type { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr int is_steady = 0; + static time_point now(); +}; + +struct now_missing { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; +}; + +struct now_type { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + using now = time_point; +}; + +struct now_not_fun { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static time_point now; +}; + +struct now_not_static { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + time_point now(); +}; + +struct now_wrong_type { + using rep = long long; + using period = micro; + using duration = microseconds; + using time_point = time_point; + static constexpr bool is_steady = false; + static duration now(); +}; + +// Check standard clocks +static_assert(is_clock::value); +static_assert(is_clock_v); +static_assert(is_clock_v); +static_assert(is_clock_v); +static_assert(is_clock_v); +static_assert(is_clock_v); +static_assert(is_clock_v); +static_assert(is_clock_v); + +// Check custom clocks +static_assert(is_clock_v); + +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); + +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); + +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); + +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(is_clock_v); + +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); + +static_assert(!is_clock_v); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2649325 +static_assert(!is_clock_v); +#endif // ^^^ no workaround ^^^ +static_assert(!is_clock_v); +static_assert(!is_clock_v); +static_assert(!is_clock_v); void test_is_leap_second(const year_month_day& ymd) { const sys_days ls{ymd}; @@ -376,11 +583,6 @@ void test_clock_cast() { assert(clock_cast(sys_seconds{sys_days{2000y / January / 1}}).time_since_epoch() == 946'684'822s); } -static_assert(is_clock_v); -static_assert(is_clock_v); -static_assert(is_clock_v); -static_assert(is_clock_v); - tzdb copy_tzdb() { const auto& my_tzdb = get_tzdb_list().front(); vector zones;