Skip to content

Commit 1248f54

Browse files
Implement LWG-4257: Stream insertion for chrono::local_time should be constrained (#5895)
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
1 parent fafda46 commit 1248f54

File tree

2 files changed

+40
-1
lines changed
  • stl/inc
  • tests/std/tests/P0355R7_calendars_and_time_zones_formatting

2 files changed

+40
-1
lines changed

stl/inc/chrono

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5302,7 +5302,9 @@ namespace chrono {
53025302
}
53035303

53045304
_EXPORT_STD template <class _CharT, class _Traits, class _Duration>
5305-
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const local_time<_Duration>& _Val) {
5305+
basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& _Os, const local_time<_Duration>& _Val)
5306+
requires requires { _Os << sys_time<_Duration>{_Val.time_since_epoch()}; }
5307+
{
53065308
return _Os << sys_time<_Duration>{_Val.time_since_epoch()};
53075309
}
53085310

tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include <timezone_data.hpp>
2222

23+
// Extended to test LWG-4257 "Stream insertion for chrono::local_time should be constrained"
24+
2325
using namespace std;
2426
using namespace chrono;
2527

@@ -1067,9 +1069,44 @@ void test_unsigned_sys_time_format_after_LWG_4274() {
10671069
assert(s == "1970-01-01 00:00:00");
10681070
}
10691071

1072+
template <typename T>
1073+
concept ostream_insertable = requires(ostream& o, const T& t) { o << t; };
1074+
1075+
template <typename Dur>
1076+
void check_stream_insertion_operator_for_duration() {
1077+
if constexpr (ostream_insertable<sys_time<Dur>>) {
1078+
ostringstream oss;
1079+
oss << sys_time<Dur>{};
1080+
assert(oss.str() == "1970-01-01 00:00:00");
1081+
}
1082+
1083+
if constexpr (ostream_insertable<local_time<Dur>>) {
1084+
ostringstream oss;
1085+
oss << local_time<Dur>{};
1086+
assert(oss.str() == "1970-01-01 00:00:00");
1087+
}
1088+
}
1089+
1090+
// Test based on example in LWG-4257
1091+
void check_stream_insertion_operator() {
1092+
// operator<< is constrained such that it does not participate when underlying duration has floating-point rep
1093+
using ok_dur = duration<long long>;
1094+
using bad_dur = duration<double>;
1095+
1096+
static_assert(ostream_insertable<sys_time<ok_dur>>);
1097+
static_assert(ostream_insertable<local_time<ok_dur>>);
1098+
check_stream_insertion_operator_for_duration<ok_dur>();
1099+
1100+
static_assert(!ostream_insertable<sys_time<bad_dur>>);
1101+
static_assert(!ostream_insertable<local_time<bad_dur>>);
1102+
check_stream_insertion_operator_for_duration<bad_dur>();
1103+
}
1104+
10701105
void test() {
10711106
test_unsigned_sys_time_format_after_LWG_4274();
10721107

1108+
check_stream_insertion_operator();
1109+
10731110
test_parse_conversion_spec<char>();
10741111
test_parse_conversion_spec<wchar_t>();
10751112

0 commit comments

Comments
 (0)