format-arg-store::args
is unintentionally not exposition-onlySection: 28.5.8.2 [format.arg.store] Status: C++23 Submitter: Casey Carter Opened: 2021-04-22 Last modified: 2023-11-22
Priority: 3
View all issues with C++23 status.
Discussion:
Despite the statement in 28.5.8.3 [format.args]/1:
An instance of
basic_format_args
provides access to formatting arguments. Implementations should optimize the representation ofbasic_format_args
for a small number of formatting arguments. [Note 1: For example, by storing indices of type alternatives separately from values and packing the former. — end note]
make_format_args
and make_wformat_args
are specified to return an object whose type is
a specialization of the exposition-only class template format-arg-store
which has a public
non-static data member that is an array
of basic_format_arg
. In order to actually
"optimize the representation of basic_format_args
" an implementation must internally avoid using
make_format_args
(and make_wformat_args
) and instead use a different mechanism to type-erase
arguments. basic_format_args
must still be convertible from format-arg-store
as
specified, however, so internally basic_format_args
must support both the bad/slow standard mechanism
and a good/fast internal-only mechanism for argument storage.
<format>
with no commensurate benefit. Indeed, naive users may make the mistake of thinking
that e.g. vformat(fmt, make_format_args(args...))
is as efficient as format(fmt, args...)
—
that's what the "Effects: Equivalent to" in 28.5.5 [format.functions]/2 implies — and
inadvertently introduce performance regressions. It would be better for both implementers and users if
format-arg-store
had no public data members and its member args
were made exposition-only.
[2021-05-10; Reflector poll]
Priority set to 3.
Tim: "The current specification of make_format_args
depends on
format-arg-store
being an aggregate,
which is no longer true with this PR."
Previous resolution [SUPERSEDED]:
This wording is relative to N4885.
Modify 28.5.1 [format.syn], header
<format>
synopsis, as indicated:[…] // 28.5.8.2 [format.arg.store], class template format-arg-store template<class Context, class... Args>structclass format-arg-store; // exposition only […]Modify 28.5.8.2 [format.arg.store] as indicated:
namespace std { template<class Context, class... Args>structclass format-arg-store { // exposition only array<basic_format_arg<Context>, sizeof...(Args)> args; // exposition only }; }
[2021-05-18; Tim updates wording.]
[2021-05-20; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4885.
Modify 28.5.1 [format.syn], header <format>
synopsis, as indicated:
[…] // 28.5.8.2 [format.arg.store], class template format-arg-store template<class Context, class... Args>structclass format-arg-store; // exposition only template<class Context = format_context, class... Args> format-arg-store<Context, Args...> make_format_args(const Args&... fmt_args); […]
Modify 28.5.8.2 [format.arg.store] as indicated:
namespace std { template<class Context, class... Args>structclass format-arg-store { // exposition only array<basic_format_arg<Context>, sizeof...(Args)> args; // exposition only }; }-1- An instance of
format-arg-store
stores formatting arguments.template<class Context = format_context, class... Args> format-arg-store<Context, Args...> make_format_args(const Args&... fmt_args);-2- Preconditions: The type
-3- Returns:typename Context::template formatter_type<Ti>
meets the Formatter requirements (28.5.6.1 [formatter.requirements]) for eachTi
inArgs
.An object of typeformat-arg-store<Context, Args...>
whoseargs
data member is initialized with{basic_format_arg<Context>(fmt_args)...}
.