This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
Section: 28.5.7.2 [format.range.formatter], 28.5.9 [format.tuple] Status: WP Submitter: Victor Zverovich Opened: 2023-02-20 Last modified: 2023-11-22
Priority: 2
View all other issues in [format.range.formatter].
View all issues with WP status.
Discussion:
formatter
specializations for ranges and tuples set debug format for underlying element formatters in their
parse
functions e.g. 28.5.7.2 [format.range.formatter] p9:
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);Effects: Parses the format specifier as a range-format-spec and stores the parsed specifiers in
*this
. The values ofopening-bracket_
,closing-bracket_
, andseparator_
are modified if and only if required by the range-type or then
option, if present. If:
— the range-type is neither
s
nor?s
,—
underlying_.set_debug_format()
is a valid expression, and— there is no range-underlying-spec,
then calls
underlying_.set_debug_format()
.
However, they don't say anything about calling parse
functions of those formatters. As as result,
formatting of nested ranges can be incorrect, e.g.
std::string s = std::format("{}", std::vector<std::vector<std::string>>{{"a, b", "c"}});
With the current specification s
is [[a, b, c]]
instead of [["a, b", "c"]]
, i.e. strings
in the output are not correctly escaped. The same is true for nested tuples and combinations of tuples and ranges.
parse
for underlying formatter.
Additionally the standard should clarify that format-spec cannot start with '}'
because that's the
implicit assumption in range formatting and what happens when format-spec is not present.
[2023-03-22; Reflector poll]
Set priority to 2 after reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N4928.
Modify 28.5.2.1 [format.string.general] p1 as indicated:
- […]
- format-specifier:
- : format-spec
- format-spec:
- as specified by the
formatter
specialization for the argument type; cannot start with}
Modify 28.5.6.1 [formatter.requirements] as indicated:
-3- Given character type
[…]charT
, output iterator typeOut
, and formatting argument typeT
, in Table 74 [tab:formatter.basic] and Table 75 [tab:formatter]:pc.begin()
points to the beginning of the format-spec (28.5.2 [format.string]) of the replacement field being formatted in the format string. If format-spec is not present or empty then eitherpc.begin() == pc.end()
or*pc.begin() == '}'
.Modify 28.5.7.2 [format.range.formatter] as indicated:
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);-9- Effects: Parses the format specifiers as a range-format-spec and stores the parsed specifiers in
*this
. Callsunderlying_.parse(ctx)
to parse format-spec in range-format-spec or, if the latter is not present, empty format-spec. The values ofopening-bracket_
,closing-bracket_
, andseparator_
are modified if and only if required by the range-type or then
option, if present. If:
(9.1) — the range-type is neither
s
nor?s
,(9.2) —
underlying_.set_debug_format()
is a valid expression, and(9.3) — there is no range-underlying-spec,
then calls
underlying_.set_debug_format()
.Modify 28.5.9 [format.tuple] as indicated:
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);-7- Effects: Parses the format specifiers as a tuple-format-spec and stores the parsed specifiers in
*this
. The values ofopening-bracket_
,closing-bracket_
, andseparator_
are modified if and only if required by the tuple-type, if present. For each elemente
inunderlying_
, callse.parse(ctx)
to parse empty format-spec and, ife.set_debug_format()
is a valid expression, callse.set_debug_format()
.
[Varna 2023-06-16; Jonathan provides tweaked wording]
Add "an" in two places.
[Varna 2023-06-16; Move to Ready]
This would allow resolving LWG 3776(i) as NAD.
[2023-11-11 Approved at November 2023 meeting in Kona. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4928.
Modify 28.5.2.1 [format.string.general] p1 as indicated:
- […]
- format-specifier:
- : format-spec
- format-spec:
- as specified by the
formatter
specialization for the argument type; cannot start with}
Modify 28.5.6.1 [formatter.requirements] as indicated:
-3- Given character type
[…]charT
, output iterator typeOut
, and formatting argument typeT
, in Table 74 [tab:formatter.basic] and Table 75 [tab:formatter]:pc.begin()
points to the beginning of the format-spec (28.5.2 [format.string]) of the replacement field being formatted in the format string. If format-spec is not present or empty then eitherpc.begin() == pc.end()
or*pc.begin() == '}'
.
Modify 28.5.7.2 [format.range.formatter] as indicated:
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);-9- Effects: Parses the format specifiers as a range-format-spec and stores the parsed specifiers in
*this
. Callsunderlying_.parse(ctx)
to parse format-spec in range-format-spec or, if the latter is not present, an empty format-spec. The values ofopening-bracket_
,closing-bracket_
, andseparator_
are modified if and only if required by the range-type or then
option, if present. If:
(9.1) — the range-type is neither
s
nor?s
,(9.2) —
underlying_.set_debug_format()
is a valid expression, and(9.3) — there is no range-underlying-spec,
then calls
underlying_.set_debug_format()
.
Modify 28.5.9 [format.tuple] as indicated:
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);-7- Effects: Parses the format specifiers as a tuple-format-spec and stores the parsed specifiers in
*this
. The values ofopening-bracket_
,closing-bracket_
, andseparator_
are modified if and only if required by the tuple-type, if present. For each elemente
inunderlying_
, callse.parse(ctx)
to parse an empty format-spec and, ife.set_debug_format()
is a valid expression, callse.set_debug_format()
.