From 9d12685230a5fa8cf1442938f70883173dc804d6 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Wed, 6 Oct 2021 16:31:47 +0800 Subject: [PATCH 1/6] Implement LWG-3554 --- stl/inc/chrono | 61 +++++++++++++------ .../test.cpp | 8 +-- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index e3f887fa27..53f493622a 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5138,53 +5138,76 @@ namespace chrono { template struct _Time_parse_iomanip { - _Time_parse_iomanip(const basic_string<_CharT, _Traits, _Alloc>& _Fmt_, _Parsable& _Tp_, + _Time_parse_iomanip(const _CharT* _Fmt_, _Parsable& _Tp_, basic_string<_CharT, _Traits, _Alloc>* _Abbrev_ = nullptr, minutes* _Offset_ = nullptr) : _Fmt{_Fmt_}, _Tp{_Tp_}, _Abbrev{_Abbrev_}, _Offset{_Offset_} {} + _Time_parse_iomanip(_Time_parse_iomanip&&) = delete; - const basic_string<_CharT, _Traits, _Alloc>& _Fmt; + const _CharT* _Fmt; _Parsable& _Tp; basic_string<_CharT, _Traits, _Alloc>* _Abbrev; minutes* _Offset; }; + template + using _Has_from_stream = void_t&>(), + _STD declval(), _STD declval<_Parsable&>(), _STD declval<_Rest>()...))>; + + template , _Parsable>> + _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp) { + return _Time_parse_iomanip<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt, _Tp}; + } + template &>(), - _STD declval(), _STD declval<_Parsable&>()))>> + class = _Has_from_stream<_CharT, _Traits, _Parsable>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp) { - return _Time_parse_iomanip{_Fmt, _Tp}; + return _Time_parse_iomanip<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt.c_str(), _Tp}; + } + + template *>> + _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { + return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev)}; } template &>(), - _STD declval(), _STD declval<_Parsable&>(), - _STD declval*>()))>> + class = _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { - return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev)}; + return _Time_parse_iomanip{_Fmt.c_str(), _Tp, _STD addressof(_Abbrev)}; + } + + template , _Parsable, basic_string<_CharT>*, minutes*>> + _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, minutes& _Offset) { + return _Time_parse_iomanip{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; } template &>(), - _STD declval(), _STD declval<_Parsable&>(), - _STD declval*>(), _STD declval()))>> + class = _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*, minutes*>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, minutes& _Offset) { - return _Time_parse_iomanip{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; + return _Time_parse_iomanip{ + _Fmt.c_str(), _Tp, static_cast*>(nullptr), &_Offset}; } template &>(), - _STD declval(), _STD declval<_Parsable&>(), - _STD declval*>(), _STD declval()))>> + class = _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*, minutes*>> + _NODISCARD auto parse( + const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { + return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; + } + + template *, minutes*>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { - return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; + return _Time_parse_iomanip{_Fmt.c_str(), _Tp, _STD addressof(_Abbrev), &_Offset}; } template basic_istream<_CharT, _Traits>& operator>>( - basic_istream<_CharT, _Traits>& _Is, const _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>& _Tpi) { - return _CHRONO from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); + basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { + return _CHRONO from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); } #endif // _HAS_CXX20 diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp index 373f7da353..969446fb08 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp @@ -147,15 +147,15 @@ void test_parse(const CharT* str, const CharT* fmt, Parsable& p, type_identity_t basic_stringstream sstr{str}; if (abbrev) { if (offset) { - sstr >> parse(basic_string{fmt}, p, *abbrev, *offset); + sstr >> parse(fmt, p, *abbrev, *offset); } else { - sstr >> parse(basic_string{fmt}, p, *abbrev); + sstr >> parse(fmt, p, *abbrev); } } else { if (offset) { - sstr >> parse(basic_string{fmt}, p, *offset); + sstr >> parse(fmt, p, *offset); } else { - sstr >> parse(basic_string{fmt}, p); + sstr >> parse(fmt, p); } } From cf46939de32492817980eb7930a42a9fda953d0d Mon Sep 17 00:00:00 2001 From: cpplearner Date: Thu, 7 Oct 2021 01:14:55 +0800 Subject: [PATCH 2/6] Avoid ABI break --- stl/inc/chrono | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 53f493622a..26eca33d89 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5136,14 +5136,27 @@ namespace chrono { return _Istr; } + template + struct _Time_parse_iomanip_c_str { + _Time_parse_iomanip_c_str(const _CharT* _Fmt_, _Parsable& _Tp_, + basic_string<_CharT, _Traits, _Alloc>* _Abbrev_ = nullptr, minutes* _Offset_ = nullptr) + : _Fmt{_Fmt_}, _Tp{_Tp_}, _Abbrev{_Abbrev_}, _Offset{_Offset_} {} + _Time_parse_iomanip_c_str(_Time_parse_iomanip_c_str&&) = delete; + + const _CharT* _Fmt; + _Parsable& _Tp; + basic_string<_CharT, _Traits, _Alloc>* _Abbrev; + minutes* _Offset; + }; + template struct _Time_parse_iomanip { - _Time_parse_iomanip(const _CharT* _Fmt_, _Parsable& _Tp_, + _Time_parse_iomanip(const basic_string<_CharT, _Traits, _Alloc>& _Fmt_, _Parsable& _Tp_, basic_string<_CharT, _Traits, _Alloc>* _Abbrev_ = nullptr, minutes* _Offset_ = nullptr) : _Fmt{_Fmt_}, _Tp{_Tp_}, _Abbrev{_Abbrev_}, _Offset{_Offset_} {} _Time_parse_iomanip(_Time_parse_iomanip&&) = delete; - const _CharT* _Fmt; + const basic_string<_CharT, _Traits, _Alloc>& _Fmt; _Parsable& _Tp; basic_string<_CharT, _Traits, _Alloc>* _Abbrev; minutes* _Offset; @@ -5155,61 +5168,66 @@ namespace chrono { template , _Parsable>> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp) { - return _Time_parse_iomanip<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt, _Tp}; + return _Time_parse_iomanip_c_str<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt, _Tp}; } template > _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp) { - return _Time_parse_iomanip<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt.c_str(), _Tp}; + return _Time_parse_iomanip{_Fmt, _Tp}; } template *>> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { - return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev)}; + return _Time_parse_iomanip_c_str{_Fmt, _Tp, _STD addressof(_Abbrev)}; } template *>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { - return _Time_parse_iomanip{_Fmt.c_str(), _Tp, _STD addressof(_Abbrev)}; + return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev)}; } template , _Parsable, basic_string<_CharT>*, minutes*>> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, minutes& _Offset) { - return _Time_parse_iomanip{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; + return _Time_parse_iomanip_c_str{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; } template *, minutes*>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, minutes& _Offset) { - return _Time_parse_iomanip{ - _Fmt.c_str(), _Tp, static_cast*>(nullptr), &_Offset}; + return _Time_parse_iomanip{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; } template *, minutes*>> _NODISCARD auto parse( const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { - return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; + return _Time_parse_iomanip_c_str{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; } template *, minutes*>> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { - return _Time_parse_iomanip{_Fmt.c_str(), _Tp, _STD addressof(_Abbrev), &_Offset}; + return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; } template basic_istream<_CharT, _Traits>& operator>>( - basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { + basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip_c_str<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { return _CHRONO from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); } + template + basic_istream<_CharT, _Traits>& operator>>( + basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { + return _CHRONO from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); + } + #endif // _HAS_CXX20 } // namespace chrono From 58af91582837807d281fd0ef2374bff97de06274 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Fri, 8 Oct 2021 04:10:40 +0800 Subject: [PATCH 3/6] Address review comments from MattStephanson --- stl/inc/chrono | 2 + .../test.cpp | 65 ++++++++++--------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 26eca33d89..a36f97421c 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5141,6 +5141,7 @@ namespace chrono { _Time_parse_iomanip_c_str(const _CharT* _Fmt_, _Parsable& _Tp_, basic_string<_CharT, _Traits, _Alloc>* _Abbrev_ = nullptr, minutes* _Offset_ = nullptr) : _Fmt{_Fmt_}, _Tp{_Tp_}, _Abbrev{_Abbrev_}, _Offset{_Offset_} {} + _Time_parse_iomanip_c_str(_Time_parse_iomanip_c_str&&) = delete; const _CharT* _Fmt; @@ -5154,6 +5155,7 @@ namespace chrono { _Time_parse_iomanip(const basic_string<_CharT, _Traits, _Alloc>& _Fmt_, _Parsable& _Tp_, basic_string<_CharT, _Traits, _Alloc>* _Abbrev_ = nullptr, minutes* _Offset_ = nullptr) : _Fmt{_Fmt_}, _Tp{_Tp_}, _Abbrev{_Abbrev_}, _Offset{_Offset_} {} + _Time_parse_iomanip(_Time_parse_iomanip&&) = delete; const basic_string<_CharT, _Traits, _Alloc>& _Fmt; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp index 969446fb08..7c96031549 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp @@ -29,7 +29,7 @@ bool test_duration_basic_out(const duration& d, const CharT* expect return ss.str() == expected; } -#define WIDEN(TYPE, STR) get(pair{STR, L##STR}); +#define WIDEN(TYPE, STR) get(pair{STR, L##STR}) template bool test_duration_locale_out() { @@ -64,8 +64,6 @@ bool test_duration_locale_out() { return ss.str() == expected; } -#undef WIDEN - void test_duration_output() { using LongRatio = ratio; assert(test_duration_basic_out(duration{1}, "1as")); @@ -128,9 +126,9 @@ void test_duration_output() { } -template -void test_parse(const CharT* str, const CharT* fmt, Parsable& p, type_identity_t*> abbrev = nullptr, - minutes* offset = nullptr) { +template +void test_parse(const CharT* str, CStringOrStdString fmt, Parsable& p, + type_identity_t*> abbrev = nullptr, minutes* offset = nullptr) { p = Parsable{}; if (abbrev) { if constexpr (is_same_v) { @@ -162,9 +160,9 @@ void test_parse(const CharT* str, const CharT* fmt, Parsable& p, type_identity_t assert(sstr); } -template -void fail_parse(const CharT* str, const CharT* fmt, Parsable& p, type_identity_t*> abbrev = nullptr, - minutes* offset = nullptr) { +template +void fail_parse(const CharT* str, CStringOrStdString fmt, Parsable& p, + type_identity_t*> abbrev = nullptr, minutes* offset = nullptr) { p = Parsable{}; if (abbrev) { if constexpr (is_same_v) { @@ -181,15 +179,15 @@ void fail_parse(const CharT* str, const CharT* fmt, Parsable& p, type_identity_t basic_stringstream sstr{str}; if (abbrev) { if (offset) { - sstr >> parse(basic_string{fmt}, p, *abbrev, *offset); + sstr >> parse(fmt, p, *abbrev, *offset); } else { - sstr >> parse(basic_string{fmt}, p, *abbrev); + sstr >> parse(fmt, p, *abbrev); } } else { if (offset) { - sstr >> parse(basic_string{fmt}, p, *offset); + sstr >> parse(fmt, p, *offset); } else { - sstr >> parse(basic_string{fmt}, p); + sstr >> parse(fmt, p); } } @@ -227,19 +225,19 @@ void test_lwg_3536() { { istringstream iss{"2:2:30"}; - iss >> parse(string{"%H:%M:%S"}, mm); + iss >> parse("%H:%M:%S", mm); assert(iss.fail() && mm == 20min); } { istringstream iss{"June"}; - iss >> parse(string{"%B"}, mm); + iss >> parse("%B", mm); assert(iss.fail() && mm == 20min); } { istringstream iss{""}; - iss >> parse(string{"%B"}, mm); + iss >> parse("%B", mm); assert(iss.fail() && mm == 20min); } } @@ -1172,36 +1170,37 @@ void parse_timepoints() { test_gh_1952(); } -void parse_wchar() { +template +void test_wchar_and_lwg_3554() { seconds time; - test_parse(L"12", L"%S", time); + test_parse(WIDEN(CharT, "12"), CStringOrStdString{WIDEN(CharT, "%S")}, time); assert(time == 12s); - test_parse(L"12", L"%M", time); + test_parse(WIDEN(CharT, "12"), CStringOrStdString{WIDEN(CharT, "%M")}, time); assert(time == 12min); - test_parse(L"30", L"%H", time); + test_parse(WIDEN(CharT, "30"), CStringOrStdString{WIDEN(CharT, "%H")}, time); assert(time == 30h); - test_parse(L" 1:23:42", L"%T", time); + test_parse(WIDEN(CharT, " 1:23:42"), CStringOrStdString{WIDEN(CharT, "%T")}, time); assert(time == 1h + 23min + 42s); - wstring tz_name; - test_parse(L"Etc/GMT+11", L"%Z", time, &tz_name); - assert(tz_name == L"Etc/GMT+11"); - fail_parse(L"Not_valid! 00", L"%Z %H", time, &tz_name); + basic_string tz_name; + test_parse(WIDEN(CharT, "Etc/GMT+11"), CStringOrStdString{WIDEN(CharT, "%Z")}, time, &tz_name); + assert(tz_name == WIDEN(CharT, "Etc/GMT+11")); + fail_parse(WIDEN(CharT, "Not_valid! 00"), CStringOrStdString{WIDEN(CharT, "%Z %H")}, time, &tz_name); weekday wd; - test_parse(L"wedNesday", L"%A", wd); + test_parse(WIDEN(CharT, "wedNesday"), CStringOrStdString{WIDEN(CharT, "%A")}, wd); assert(wd == Wednesday); month m; - test_parse(L"deCeMbeR", L"%b", m); + test_parse(WIDEN(CharT, "deCeMbeR"), CStringOrStdString{WIDEN(CharT, "%b")}, m); assert(m == December); sys_seconds st; - test_parse(L"oct 29 19:01:42 2020", L"%c", st); + test_parse(WIDEN(CharT, "oct 29 19:01:42 2020"), CStringOrStdString{WIDEN(CharT, "%c")}, st); assert(st == sys_days{2020y / October / 29d} + 19h + 1min + 42s); - fail_parse(L"ab", L"a%nb", time); - test_parse(L"a b", L"a%nb", time); - fail_parse(L"a b", L"a%nb", time); + fail_parse(WIDEN(CharT, "ab"), CStringOrStdString{WIDEN(CharT, "a%nb")}, time); + test_parse(WIDEN(CharT, "a b"), CStringOrStdString{WIDEN(CharT, "a%nb")}, time); + fail_parse(WIDEN(CharT, "a b"), CStringOrStdString{WIDEN(CharT, "a%nb")}, time); } void test_parse() { @@ -1216,7 +1215,9 @@ void test_parse() { parse_other_week_date(); parse_whitespace(); parse_timepoints(); - parse_wchar(); + test_wchar_and_lwg_3554(); + test_wchar_and_lwg_3554(); + test_wchar_and_lwg_3554(); } void test() { From 40ec53233fd4d1a9726825a8e38226d01690f73b Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Thu, 28 Oct 2021 01:55:39 +0800 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: Casey Carter --- stl/inc/chrono | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index a36f97421c..511341f03c 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5221,13 +5221,15 @@ namespace chrono { template basic_istream<_CharT, _Traits>& operator>>( basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip_c_str<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { - return _CHRONO from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); + from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL + return _Is; } template basic_istream<_CharT, _Traits>& operator>>( basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip<_CharT, _Traits, _Alloc, _Parsable>&& _Tpi) { - return _CHRONO from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); + from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL + return _Is; } #endif // _HAS_CXX20 From 6f71e786dfdf80545aa8cc170348d8b462fea93f Mon Sep 17 00:00:00 2001 From: cpplearner Date: Thu, 28 Oct 2021 02:08:26 +0800 Subject: [PATCH 5/6] call `from_stream` unqualified --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 511341f03c..cf023a1f1f 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5165,7 +5165,7 @@ namespace chrono { }; template - using _Has_from_stream = void_t&>(), + using _Has_from_stream = void_t&>(), _STD declval(), _STD declval<_Parsable&>(), _STD declval<_Rest>()...))>; template , _Parsable>> From a27e977ce608b05060e5f8888d280623a9e13011 Mon Sep 17 00:00:00 2001 From: cpplearner Date: Thu, 28 Oct 2021 16:29:08 +0800 Subject: [PATCH 6/6] Address review comments from StephanTLavavej --- stl/inc/chrono | 22 ++++++++++--------- .../test.cpp | 13 ++++++----- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index cf023a1f1f..c5e3638d21 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -5165,54 +5165,56 @@ namespace chrono { }; template - using _Has_from_stream = void_t&>(), - _STD declval(), _STD declval<_Parsable&>(), _STD declval<_Rest>()...))>; + using _Has_from_stream = + decltype(static_cast(from_stream(_STD declval&>(), + _STD declval(), _STD declval<_Parsable&>(), _STD declval<_Rest>()...)), + 0); // intentional ADL - template , _Parsable>> + template , _Parsable> = 0> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp) { return _Time_parse_iomanip_c_str<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt, _Tp}; } template > + _Has_from_stream<_CharT, _Traits, _Parsable> = 0> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp) { return _Time_parse_iomanip{_Fmt, _Tp}; } template *>> + _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*> = 0> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { return _Time_parse_iomanip_c_str{_Fmt, _Tp, _STD addressof(_Abbrev)}; } template *>> + _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*> = 0> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev) { return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev)}; } template , _Parsable, basic_string<_CharT>*, minutes*>> + _Has_from_stream<_CharT, char_traits<_CharT>, _Parsable, basic_string<_CharT>*, minutes*> = 0> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp, minutes& _Offset) { return _Time_parse_iomanip_c_str{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; } template *, minutes*>> + _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*, minutes*> = 0> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, minutes& _Offset) { return _Time_parse_iomanip{_Fmt, _Tp, static_cast*>(nullptr), &_Offset}; } template *, minutes*>> + _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*, minutes*> = 0> _NODISCARD auto parse( const _CharT* _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { return _Time_parse_iomanip_c_str{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; } template *, minutes*>> + _Has_from_stream<_CharT, _Traits, _Parsable, basic_string<_CharT, _Traits, _Alloc>*, minutes*> = 0> _NODISCARD auto parse(const basic_string<_CharT, _Traits, _Alloc>& _Fmt, _Parsable& _Tp, basic_string<_CharT, _Traits, _Alloc>& _Abbrev, minutes& _Offset) { return _Time_parse_iomanip{_Fmt, _Tp, _STD addressof(_Abbrev), &_Offset}; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp index 7c96031549..1a1c20b3c8 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp @@ -127,7 +127,7 @@ void test_duration_output() { template -void test_parse(const CharT* str, CStringOrStdString fmt, Parsable& p, +void test_parse(const CharT* str, const CStringOrStdString& fmt, Parsable& p, type_identity_t*> abbrev = nullptr, minutes* offset = nullptr) { p = Parsable{}; if (abbrev) { @@ -161,7 +161,7 @@ void test_parse(const CharT* str, CStringOrStdString fmt, Parsable& p, } template -void fail_parse(const CharT* str, CStringOrStdString fmt, Parsable& p, +void fail_parse(const CharT* str, const CStringOrStdString& fmt, Parsable& p, type_identity_t*> abbrev = nullptr, minutes* offset = nullptr) { p = Parsable{}; if (abbrev) { @@ -1171,7 +1171,7 @@ void parse_timepoints() { } template -void test_wchar_and_lwg_3554() { +void test_io_manipulator() { seconds time; test_parse(WIDEN(CharT, "12"), CStringOrStdString{WIDEN(CharT, "%S")}, time); assert(time == 12s); @@ -1215,9 +1215,10 @@ void test_parse() { parse_other_week_date(); parse_whitespace(); parse_timepoints(); - test_wchar_and_lwg_3554(); - test_wchar_and_lwg_3554(); - test_wchar_and_lwg_3554(); + test_io_manipulator(); + test_io_manipulator(); + test_io_manipulator(); + test_io_manipulator(); } void test() {