This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3269. Parse manipulators do not specify the result of the extraction from stream

Section: 29.13 [time.parse] Status: C++20 Submitter: Tomasz Kamiński Opened: 2019-09-01 Last modified: 2021-02-25

Priority: 2

View all other issues in [time.parse].

View all issues with C++20 status.

Discussion:

None of the `parse` manipulators for the `chrono` types specifies the result of the extraction from the stream, as consequence they cannot be chained with the other read operations (at least portably). For example the following code is not required to work:

>     std::chrono::sys_stime s;
>     int x;
>     std::cin >> std::chrono::parse("%X", s) >> x;

[2019-10 Priority set to 2 after reflector discussion]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4830.

> > [Drafting note: As a drive-by fix the Remarks element is also converted to a Constraints element. The wording integrates the resolution for LWG 3235.

> 1. Modify 29.13 [time.parse] as indicated:

>    > -1- Each parse overload specified in this subclause calls `from_stream` unqualified, so as to enable argument dependent lookup (6.5.4 [basic.lookup.argdep]). In the following paragraphs, let `is` denote an object of type `basic_istream<charT, traits>` and let `I` be `basic_istream<charT, traits>&`, where `charT` and `traits` are template parameters in that context.

>    >     template<class charT, class traits, class Alloc, class Parsable>
>    >       unspecified
>    >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);

>    > > -2- Remarks Constraints: This function shall not participate in overload resolution unless The expression

>    > > >     from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp)

>    > > is a valid expression well-formed when treated as an unevaluated operand.

>    > > -3- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp)`.

>    >     template<class charT, class traits, class Alloc, class Parsable>
>    >       unspecified
>    >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
>    >               basic_string<charT, traits, Alloc>& abbrev);

>    > > -4- Remarks Constraints: This function shall not participate in overload resolution unless The expression

>    > > >     from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, addressof(abbrev))

>    > > is a valid expression well-formed when treated as an unevaluated operand.

>    > > -5- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, abbrev)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp, addressof(abbrev))`.

>    >     template<class charT, class traits, class Alloc, class Parsable>
>    >       unspecified
>    >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
>    >               minutes& offset);

>    > > -6- Remarks Constraints: This function shall not participate in overload resolution unless The expression

>    > > >     from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp,
>    > > >                 declval<basic_string<charT, traits, Alloc>*>()nullptr, &offset)

>    > > is a valid expression well-formed when treated as an unevaluated operand.

>    > > -7- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, offset)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp, static_cast<basic_string<charT, traits, Alloc>*>(nullptr), &offset)`.

>    >     template<class charT, class traits, class Alloc, class Parsable>
>    >       unspecified
>    >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
>    >               basic_string<charT, traits, Alloc>& abbrev, minutes& offset);

>    > > -8- Remarks Constraints: This function shall not participate in overload resolution unless The expression

>    > > >     from_stream(declval<basic_istream<charT, traits>&>(),
>    > > >                 fmt.c_str(), tp, addressof(abbrev), &offset)

>    > > is a valid expression well-formed when treated as an unevaluated operand.

>    > > -9- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, abbrev, offset)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp, addressof(abbrev), &offset)`.

[2020-02-13, Prague]

Issue wording has been rebased.

[2020-02 Status to Immediate on Friday morning in Prague.]

Proposed resolution:

This wording is relative to N4849.

1. Modify 29.13 [time.parse] as indicated:

   > -1- Each `parse` overload specified in this subclause calls `from_stream` unqualified, so as to enable argument dependent lookup (6.5.4 [basic.lookup.argdep]). In the following paragraphs, let `is` denote an object of type `basic_istream<charT, traits>` and let `I` be `basic_istream<charT, traits>&`, where `charT` and `traits` are template parameters in that context.

   >     template<class charT, class traits, class Alloc, class Parsable>
   >       unspecified
   >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);

   > > -2- Constraints: The expression

   > > >     from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp)

   > > is a valid expression well-formed when treated as an unevaluated operand.

   > > -3- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp)`.

   >     template<class charT, class traits, class Alloc, class Parsable>
   >       unspecified
   >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
   >               basic_string<charT, traits, Alloc>& abbrev);

   > > -4- Constraints: The expression

   > > >     from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, addressof(abbrev))

   > > is a valid expression well-formed when treated as an unevaluated operand.

   > > -5- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, abbrev)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp, addressof(abbrev))`.

   >     template<class charT, class traits, class Alloc, class Parsable>
   >       unspecified
   >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
   >               minutes& offset);

   > > -6- Constraints: The expression

   > > >     from_stream(declval<basic_istream<charT, traits>&>(),
   > > >                 fmt.c_str(), tp,
   > > >                 declval<basic_string<charT, traits, Alloc>*>(),
   > > >                 &offset)

   > > is well-formed when treated as an unevaluated operand.

   > > -7- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, offset)` has type `I`, value `is`, and calls

   > > >     from_stream(is,
   > > >                 fmt.c_str(), tp,
   > > >                 static_cast<basic_string<charT, traits, Alloc>*>(nullptr),
   > > >                 &offset)

   >     template<class charT, class traits, class Alloc, class Parsable>
   >       unspecified
   >         parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
   >               basic_string<charT, traits, Alloc>& abbrev, minutes& offset);

   > > -8- Constraints: The expression

   > > >     from_stream(declval<basic_istream<charT, traits>&>(),
   > > >                 fmt.c_str(), tp, addressof(abbrev), &offset)

   > > is a valid expression well-formed when treated as an unevaluated operand.

   > > -9- Returns: A manipulator such that, when extracted from a `basic_istream<charT, traits> is`,the expression `is >> parse(fmt, tp, abbrev, offset)` has type `I`, value `is`, and calls `from_stream(is, fmt.c_str(), tp, addressof(abbrev), &offset)`.