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- RemarksConstraints: This function shall not participate in overload resolution unlessThe expression

    from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp)
    
    is a valid expressionwell-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- RemarksConstraints: This function shall not participate in overload resolution unlessThe expression

    from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, addressof(abbrev))
    
    is a valid expressionwell-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- RemarksConstraints: This function shall not participate in overload resolution unlessThe expression

    from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, 
                declval<basic_string<charT, traits, Alloc>*>()nullptr, &offset)
    
    is a valid expressionwell-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- RemarksConstraints: This function shall not participate in overload resolution unlessThe expression

    from_stream(declval<basic_istream<charT, traits>&>(),
                fmt.c_str(), tp, addressof(abbrev), &offset)
    
    is a valid expressionwell-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 expressionwell-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 expressionwell-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 expressionwell-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).