From 10a4e29ef60b0c80ce1c62b342bbbfce1a97a3b3 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 12 Mar 2025 12:28:43 +0800 Subject: [PATCH 1/3] Implement LWG-3956 --- stl/inc/chrono | 24 +++++++--- .../test.cpp | 44 +++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index b71235f710d..93cc2efc018 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -4608,6 +4608,22 @@ namespace chrono { return _Istr; } + namespace _From_stream_adl_only { +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1681199 + void from_stream() = delete; // Block unqualified name lookup +#else // ^^^ no workaround / workaround vvv + void from_stream(); +#endif // ^^^ workaorund ^^^ + + template + concept _Can_from_stream = requires( + basic_istream<_CharT, _Traits>& __istr, const _CharT* __s, _Parsable& __parsed, _Rest&&... __rest_args) { + from_stream(__istr, +__s, __parsed, _STD forward<_Rest>(__rest_args)...); // intentional ADL + } + } // namespace _From_stream_adl_only + + using _From_stream_adl_only::_Can_from_stream; + template struct _Time_parse_iomanip_c_str { _Time_parse_iomanip_c_str(const _CharT* _Fmt_, _Parsable& _Tp_, @@ -4618,6 +4634,7 @@ namespace chrono { friend basic_istream<_CharT, _Traits>& operator>>( basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip_c_str&& _Tpi) { + using _From_stream_adl_only::from_stream; from_stream(_Is, _Tpi._Fmt, _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL return _Is; } @@ -4638,6 +4655,7 @@ namespace chrono { friend basic_istream<_CharT, _Traits>& operator>>( basic_istream<_CharT, _Traits>& _Is, _Time_parse_iomanip&& _Tpi) { + using _From_stream_adl_only::from_stream; from_stream(_Is, _Tpi._Fmt.c_str(), _Tpi._Tp, _Tpi._Abbrev, _Tpi._Offset); // intentional ADL return _Is; } @@ -4648,12 +4666,6 @@ namespace chrono { minutes* _Offset; }; - template - concept _Can_from_stream = requires( - basic_istream<_CharT, _Traits>& __istr, const _CharT* __s, _Parsable& __parsed, _Rest&&... __rest_args) { - from_stream(__istr, +__s, __parsed, _STD forward<_Rest>(__rest_args)...); // intentional ADL - }; - _EXPORT_STD template > _Parsable> _NODISCARD auto parse(const _CharT* _Fmt, _Parsable& _Tp) { return _Time_parse_iomanip_c_str<_CharT, char_traits<_CharT>, allocator<_CharT>, _Parsable>{_Fmt, _Tp}; 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 8b394ab63ce..873241cd102 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 @@ -1247,8 +1247,52 @@ void test_io_manipulator() { fail_parse(WIDEN(CharT, "a b"), CStringOrStdString{WIDEN(CharT, "a%nb")}, time); } +namespace lwg_3956 { + struct has_adl_from_stream { + int value = 0; + + template + friend basic_istream& from_stream( + basic_istream& istr, const CharT*, has_adl_from_stream& parsed, ArgTypes&&...) { + parsed.value = 42; + return istr; + } + }; + + struct has_no_adl_from_stream { + operator year&() &; + }; + + template + concept can_parse = requires(ArgTypes&&... args) { parse(forward(args)...); }; + + static_assert(can_parse); + static_assert(can_parse); + static_assert(can_parse); + static_assert(can_parse); + + static_assert(!can_parse); + static_assert(!can_parse); + static_assert(!can_parse); + static_assert(!can_parse); +} // namespace lwg_3956 + +void test_lwg_3956() { + { + lwg_3956::has_adl_from_stream parsed{}; + test_parse("", "", parsed); + assert(parsed.value == 42); + } + { + lwg_3956::has_adl_from_stream parsed{}; + test_parse(L"", L"", parsed); + assert(parsed.value == 42); + } +} + void test_parse() { test_lwg_3536(); + test_lwg_3956(); parse_seconds(); parse_minutes(); parse_hours(); From b27bd2f5a3a44ae86b5bce4043cd38db39c5b33c Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 12 Mar 2025 13:28:07 +0800 Subject: [PATCH 2/3] Fix copy-pasta --- stl/inc/chrono | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 93cc2efc018..8f0f6a6b0ee 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -4613,13 +4613,13 @@ namespace chrono { void from_stream() = delete; // Block unqualified name lookup #else // ^^^ no workaround / workaround vvv void from_stream(); -#endif // ^^^ workaorund ^^^ +#endif // ^^^ workaround ^^^ template concept _Can_from_stream = requires( basic_istream<_CharT, _Traits>& __istr, const _CharT* __s, _Parsable& __parsed, _Rest&&... __rest_args) { from_stream(__istr, +__s, __parsed, _STD forward<_Rest>(__rest_args)...); // intentional ADL - } + }; } // namespace _From_stream_adl_only using _From_stream_adl_only::_Can_from_stream; From 850fc929c76be41bbd73a2ff9f9a2b5548f1303e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 12 Mar 2025 12:17:17 -0700 Subject: [PATCH 3/3] Include `` for `basic_istream`. --- tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp | 1 + 1 file changed, 1 insertion(+) 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 873241cd102..a5683460375 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 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include