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.
Section: 28.5.5 [format.functions] Status: C++20 Submitter: Great Britain Opened: 2019-11-17 Last modified: 2021-02-25
Priority: Not Prioritized
View all other issues in [format.functions].
View all issues with C++20 status.
Discussion:
Addresses GB 229
Formatting functions don't allow throwing on incorrect arguments.
std::format
is only allowed to throw if fmt
is not a format string, but the
intention is it also throws for errors during formatting, e.g. there are fewer arguments than
required by the format string.
Proposed change:
Allow exceptions even when the format string is valid. Possibly state the Effects: more precisely.
Victor Zverovich:
LEWG approved resolution of this NB comment as an LWG issue.
Previous resolution [SUPERSEDED]:This wording is relative to N4835.
[Drafting Note: Depending on whether LWG 3336(i)'s wording has been accepted when this issue's wording has been accepted, two mutually exclusive options are prepared, depicted below by Option A and Option B, respectively.]
Option A (LWG 3336(i) has been accepted)
Change 28.5.2.1 [format.string.general] as follows:
-1- A format string for arguments
args
is a (possibly empty) sequence of replacement fields, escape sequences, and characters other than{
and}
. […]-2- The arg-id field specifies the index of the argument in
args
whose value is to be formatted and inserted into the output instead of the replacement field. If there is no argument with the index arg-id inargs
, the string is not a format string. The optional format-specifier field explicitly specifies a format for the replacement value.[…]
-5- The format-spec field contains format specifications that define how the value should be presented. Each type can define its own interpretation of the format-spec field. If format-spec doesn't conform to the format specifications for the argument in
args
referred to by arg-id, the string is not a format string. […]Before 28.5.5 [format.functions] insert a new sub-clause as indicated:
20.20.? Error reporting [format.err.report]
-?- Formatting functions throw exceptions to report formatting and other errors. They throw
format_error
if an argumentfmt
is passed that is not a format string for argumentsargs
and propagate exceptions thrown byformatter
specializations and iterator operations. Failure to allocate storage is reported by throwing an exception as described in 16.4.6.14 [res.on.exception.handling].Modify 28.5.5 [format.functions] as indicated:
string vformat(string_view fmt, format_args args); wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);[…]-6- […]
-7- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class Out> Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); template<class Out> Out vformat_to(Out out, const locale& loc, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, const locale& loc, wstring_view fmt, format_args_t<Out, wchar_t> args);[…][…]
-15- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wstring_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wstring_view fmt, const Args&... args);[…][…]
-21- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class... Args> size_t formatted_size(string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(wstring_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);[…]
-25- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringOption B (LWG 3336(i) has not been accepted)
Change 28.5.2.1 [format.string.general] as follows:
-1- A format string for arguments
args
is a (possibly empty) sequence of replacement fields, escape sequences, and characters other than{
and}
. […]-2- The arg-id field specifies the index of the argument in
args
whose value is to be formatted and inserted into the output instead of the replacement field. If there is no argument with the index arg-id inargs
, the string is not a format string. The optional format-specifier field explicitly specifies a format for the replacement value.[…]
-5- The format-spec field contains format specifications that define how the value should be presented. Each type can define its own interpretation of the format-spec field. If format-spec doesn't conform to the format specifications for the argument in
args
referred to by arg-id, the string is not a format string. […]Modify 28.5.5 [format.functions] as indicated:
string vformat(string_view fmt, format_args args); wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);[…]-6- […]
-7- Throws:
format_error
iffmt
is not a format string forargs
.template<class Out> Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); template<class Out> Out vformat_to(Out out, const locale& loc, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, const locale& loc, wstring_view fmt, format_args_t<Out, wchar_t> args);[…][…]
-15- Throws:
format_error
iffmt
is not a format string forargs
.template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wstring_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wstring_view fmt, const Args&... args);[…][…]
-21- Throws:
format_error
iffmt
is not a format string forargs
.template<class... Args> size_t formatted_size(string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(wstring_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);[…]
-25- Throws:
format_error
iffmt
is not a format string forargs
.
[2020-02-12, Prague; LWG discussion]
Option A is the only one we look at to resolve LWG 3336(i) as well. During the discussions some wording refinements have been suggested that are integrated below.
Proposed resolution:
This wording is relative to N4849.
Change 28.5.2.1 [format.string.general] as follows:
-1- A format string for arguments
args
is a (possibly empty) sequence of replacement fields, escape sequences, and characters other than{
and}
. […]-2- The arg-id field specifies the index of the argument in
args
whose value is to be formatted and inserted into the output instead of the replacement field. If there is no argument with the index arg-id inargs
, the string is not a format string forargs
. The optional format-specifier field explicitly specifies a format for the replacement value.[…]
-5- The format-spec field contains format specifications that define how the value should be presented. Each type can define its own interpretation of the format-spec field. If format-spec does not conform to the format specifications for the argument type referred to by arg-id, the string is not a format string for
args
. […]
Before 28.5.5 [format.functions] insert a new sub-clause as indicated:
20.20.? Error reporting [format.err.report]
-?- Formatting functions throw
format_error
if an argumentfmt
is passed that is not a format string forargs
. They propagate exceptions thrown by operations offormatter
specializations and iterators. Failure to allocate storage is reported by throwing an exception as described in 16.4.6.14 [res.on.exception.handling].
Modify 28.5.5 [format.functions] as indicated:
string vformat(string_view fmt, format_args args); wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);[…]-6- […]
-7- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class Out> Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); template<class Out> Out vformat_to(Out out, const locale& loc, string_view fmt, format_args_t<Out, char> args); template<class Out> Out vformat_to(Out out, const locale& loc, wstring_view fmt, format_args_t<Out, wchar_t> args);[…][…]
-15- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wstring_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, string_view fmt, const Args&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wstring_view fmt, const Args&... args);[…][…]
-21- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format stringtemplate<class... Args> size_t formatted_size(string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(wstring_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, string_view fmt, const Args&... args); template<class... Args> size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);[…]
-25- Throws:
As specified in 28.5.3 [format.err.report].format_error
iffmt
is not a format string