This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
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(i)). 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 expressionfmtfor the first overload andfmt.c_str()for the second overload. Lettraitsbechar_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 expressionfmtfor 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 expressionfmtfor the first overload andfmt.c_str()for the second overload. Lettraitsbechar_traits<charT>andAllocbeallocator<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 expressionfmtfor 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)