From 16589dc46c45cc6d66369425c158e2f3fe3c14fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Michal?= Date: Fri, 21 Nov 2025 13:11:57 +0100 Subject: [PATCH 1/2] Constrain operator<< for chrono::local_time. --- stl/inc/chrono | 4 ++- .../test.cpp | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index deed0e8b51f..f6ad7aa9cd2 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5294,7 +5294,9 @@ namespace chrono { } _EXPORT_STD template - basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const local_time<_Duration>& _Val) { + basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const local_time<_Duration>& _Val) + requires requires { _Os << sys_time<_Duration>{_Val.time_since_epoch()}; } + { return _Os << sys_time<_Duration>{_Val.time_since_epoch()}; } diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index ad371a4d257..1c3c8a51ebc 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -20,6 +20,8 @@ #include +// Extended to test LWG-4257 "Stream insertion for chrono::local_time should be constrained" + using namespace std; using namespace chrono; @@ -1061,7 +1063,39 @@ void test_locale() { assert(stream(year_month_weekday_last{2021y / May / Tuesday[last]}) == STR("2021/Mai/Di[last]")); } +template +concept ostream_insertable = requires(std::ostream& o, const T& t) { o << t; }; + +template +void check_stream_insertion_operator_for_duration() { + if constexpr (ostream_insertable>) { + std::cout << sys_time{}; + } + if constexpr (ostream_insertable>) { + std::cout << local_time{}; + } +} + +// Test based on example in LWG-4257 (https://cplusplus.github.io/LWG/issue4257) +void check_stream_insertion_operator() { + + // operator<< is constrained such that it does not participate when underlying duration has floating point rep + using ok_dur = duration; + using bad_dur = duration; + + static_assert(ostream_insertable>); + static_assert(ostream_insertable>); + check_stream_insertion_operator_for_duration(); + + static_assert(!ostream_insertable>); + static_assert(!ostream_insertable>); + check_stream_insertion_operator_for_duration(); +} + void test() { + + check_stream_insertion_operator(); + test_parse_conversion_spec(); test_parse_conversion_spec(); From dbb77b9ffede36c7ce83ca17145ec471f10d58f1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 24 Nov 2025 11:51:26 -0800 Subject: [PATCH 2/2] Code review feedback. --- .../test.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index 1c3c8a51ebc..65a8bc383cf 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -1064,22 +1064,26 @@ void test_locale() { } template -concept ostream_insertable = requires(std::ostream& o, const T& t) { o << t; }; +concept ostream_insertable = requires(ostream& o, const T& t) { o << t; }; template void check_stream_insertion_operator_for_duration() { if constexpr (ostream_insertable>) { - std::cout << sys_time{}; + ostringstream oss; + oss << sys_time{}; + assert(oss.str() == "1970-01-01 00:00:00"); } + if constexpr (ostream_insertable>) { - std::cout << local_time{}; + ostringstream oss; + oss << local_time{}; + assert(oss.str() == "1970-01-01 00:00:00"); } } -// Test based on example in LWG-4257 (https://cplusplus.github.io/LWG/issue4257) +// Test based on example in LWG-4257 void check_stream_insertion_operator() { - - // operator<< is constrained such that it does not participate when underlying duration has floating point rep + // operator<< is constrained such that it does not participate when underlying duration has floating-point rep using ok_dur = duration; using bad_dur = duration; @@ -1093,7 +1097,6 @@ void check_stream_insertion_operator() { } void test() { - check_stream_insertion_operator(); test_parse_conversion_spec();