chrono::parse
needs const charT*
and basic_string_view<charT>
overloadsSection: 30.13 [time.parse] Status: C++23 Submitter: Howard Hinnant Opened: 2021-05-22 Last modified: 2023-11-22
Priority: 2
View other active issues in [time.parse].
View all other issues in [time.parse].
View all issues with C++23 status.
Discussion:
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.
[2021-05-26; Reflector poll]
Set priority to 2 after reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N4885.
Modify 30.2 [time.syn], header
<chrono>
synopsis, as indicated:[…] namespace chrono { // 30.13 [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 30.13 [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 toreturn 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 toreturn 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 toreturn 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 toreturn 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 toreturn 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 toreturn 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 toreturn 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 toreturn 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 expressionis >> parse(fmt, tp)
has typeI
, has valueis
, and callsfrom_stream(is, fmt.c_str(), tp)
.
[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.
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-06-23; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4885.
Modify 30.2 [time.syn], header <chrono>
synopsis, as indicated:
[…] namespace chrono { // 30.13 [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 30.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.
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
-2- Constraints: The expressionfmt
for the first overload andfmt.c_str()
for the second overload. Lettraits
bechar_traits<charT>
for the first overload.from_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 expressionis >> parse(fmt, tp)
has typeI
, has valueis
, and callsfrom_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
-4- Constraints: The expressionfmt
for the first overload andfmt.c_str()
for the second overload.from_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 expressionis >> parse(fmt, tp, abbrev)
has typeI
, has valueis
, and callsfrom_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
-6- Constraints: The expressionfmt
for the first overload andfmt.c_str()
for the second overload. Lettraits
bechar_traits<charT>
andAlloc
beallocator<charT>
for the first overload.from_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 expressionis >> parse(fmt, tp, offset)
has typeI
, has valueis
, 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
-8- Constraints: The expressionfmt
for the first overload andfmt.c_str()
for the second overload.from_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 expressionis >> parse(fmt, tp, abbrev, offset)
has typeI
, has valueis
, and callsfrom_stream(is,
.fmt.c_str()F, tp, addressof(abbrev), &offset)