Created on 2021-05-22.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to N4885.
Modify [time.syn], header <chrono> synopsis, as indicated:
[…] namespace chrono { // [time.parse], parsing template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>&formatfmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>&formatfmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>&formatfmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>&formatfmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); […] } […]
Modify [time.parse] as indicated:
-1- Each parse overload specified in this subclause calls from_stream unqualified, so as to enable argument dependent lookup ([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.
-?- Recommended practice: Implementations should make it difficult to accidentally store or use a manipulator that may contain a dangling reference to a format string, for example by making the manipulators produced by parse immovable and preventing stream extraction into an lvalue of such a manipulator type.template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);-?- Let F be fmt for the first overload and fmt.c_str() for the second overload. Let traits be char_traits<charT> for the first overload.
-2- Constraints: The expressionfrom_stream(declval<basic_istream<charT, traits>&>(),fmt.c_str()F, tp)is well-formed when treated as an unevaluated operand.
-3- Returns: A manipulator such that the expression is >> parse(fmt, tp) has type I, has value is, and calls from_stream(is,fmt.c_str()F, tp).template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); 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);-?- Let F be fmt for the first overload and fmt.c_str() for the second overload.
-4- Constraints: The expressionfrom_stream(declval<basic_istream<charT, traits>&>(),fmt.c_str()F, tp, addressof(abbrev))is well-formed when treated as an unevaluated operand.
-5- Returns: A manipulator such that the expression is >> parse(fmt, tp, abbrev) has type I, has value is, and calls from_stream(is,fmt.c_str()F, tp, addressof(abbrev)).template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, minutes& offset);-?- Let F be fmt for the first overload and fmt.c_str() for the second overload. Let traits be char_traits<charT> and Alloc be allocator<charT> for the first overload.
-6- Constraints: The expressionfrom_stream(declval<basic_istream<charT, traits>&>(),fmt.c_str()F, tp, declval<basic_string<charT, traits, Alloc>*>(), &offset)is well-formed when treated as an unevaluated operand.
-7- Returns: A manipulator such that the expression is >> parse(fmt, tp, offset) has type I, has value is, and calls:from_stream(is,fmt.c_str()F, tp, static_cast<basic_string<charT, traits, Alloc>*>(nullptr), &offset)template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& 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);-?- Let F be fmt for the first overload and fmt.c_str() for the second overload.
-8- Constraints: The expressionfrom_stream(declval<basic_istream<charT, traits>&>(),fmt.c_str()F, tp, addressof(abbrev), &offset)is well-formed when treated as an unevaluated operand.
-9- Returns: A manipulator such that the expression is >> parse(fmt, tp, abbrev, offset) has type I, has value is, and calls from_stream(is,fmt.c_str()F, tp, addressof(abbrev), &offset).
[ 2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP. ]
[ 2021-06-23; Reflector poll ]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[ 2021-06-02 Tim comments and provides updated wording ]
The current specification suggests that parse takes a reference to the format string (stream extraction on the resulting manipulator is specified to call from_stream on fmt.c_str(), not some copy), so we can't call it with a temporary string.
Additionally, since the underlying API (from_stream) requires a null-terminated string, the usual practice is to avoid providing a string_view overload (see, e.g., LWG 3430). The wording below therefore only provides const charT* overloads. It does not use "Equivalent to" to avoid requiring that the basic_string overload and the const charT* overload return the same type. As the manipulator is intended to be immediately consumed, the wording also adds normative encouragement to make misuse more difficult.[ 2021-05-26; Reflector poll ]
Set priority to 2 after reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N4885.
Modify [time.syn], header <chrono> synopsis, as indicated:
[…] namespace chrono { // [time.parse], parsing template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp); template<class charT, class traits, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); […] } […]
Modify [time.parse] as indicated:
template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp);-?- Constraints: The expression
from_stream(declval<basic_istream<charT>&>(), fmt, tp)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT>{fmt}, tp);template<class charT, class traits, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt.data(), tp)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits>{fmt}, tp);template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt, tp, addressof(abbrev))is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits, Alloc>{fmt}, tp, abbrev);template<class charT, class traits, class Alloc, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt.data(), tp, addressof(abbrev))is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits, Alloc>{fmt}, tp, abbrev);template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset);-?- Constraints: The expression
from_stream(declval<basic_istream<charT>&>(), fmt, tp, declval<basic_string<charT>*>(), &offset)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT>{fmt}, tp, offset);template<class charT, class traits, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, minutes& offset);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt.data(), tp, declval<basic_string<charT, traits>*>(), &offset)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits>{fmt}, tp, offset);template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt, tp, addressof(abbrev), &offset)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits, Alloc>{fmt}, tp, abbrev, offset);template<class charT, class traits, class Alloc, class Parsable> unspecified parse(basic_string_view<charT, traits> fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset);-?- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt.data(), tp, addressof(abbrev), &offset)is well-formed when treated as an unevaluated operand.
-?- Effects: Equivalent to return parse(basic_string<charT, traits, Alloc>{fmt}, tp, abbrev, offset);template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp);-2- Constraints: The expression
from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp)is well-formed when treated as an unevaluated operand.
-3- Returns: A manipulator such that the expression is >> parse(fmt, tp) has type I, has value is, and calls from_stream(is, fmt.c_str(), tp).
The chrono::parse functions take const basic_string<charT, traits, Alloc>& parameters to specify the format strings for the parse. Due to an oversight on my part in the proposal, overloads taking const charT* and basic_string_view<charT, traits> were omitted. These are necessary when the supplied arguments is a string literal or string_view respectively:
in >> parse("%F %T", tp);
These overloads have been implemented in the example implementation.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2021-10-14 09:56:08 | admin | set | messages: + msg12123 |
2021-10-14 09:56:08 | admin | set | status: voting -> wp |
2021-09-29 12:57:28 | admin | set | status: ready -> voting |
2021-06-23 14:16:45 | admin | set | messages: + msg11960 |
2021-06-23 14:16:45 | admin | set | status: new -> ready |
2021-06-02 05:33:21 | admin | set | messages: + msg11864 |
2021-05-26 10:52:50 | admin | set | messages: + msg11853 |
2021-05-22 22:17:34 | admin | set | messages: + msg11845 |
2021-05-22 00:00:00 | admin | create |