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.

### 3544. `format-arg-store::args` is unintentionally not exposition-only

Section: 20.20.7.2 [format.arg.store] Status: WP Submitter: Casey Carter Opened: 2021-04-22 Last modified: 2021-06-07

Priority: 3

View all issues with WP status.

Discussion:

Despite the statement in 20.20.7.3 [format.args]/1:

> An instance of `basic_format_args` provides access to formatting arguments. Implementations should optimize the representation of `basic_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.

While this complicated state of affairs is technically implementable, it greatly complicates the implementation of `<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 20.20.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.

> 1. Modify 20.20.1 [format.syn], header `<format>` synopsis, as indicated:

>    >     […]
>    >     // 20.20.7.2 [format.arg.store], class template format-arg-store
>    >     template<class Context, class... Args> structclass format-arg-store; // exposition only
>    >     […]

> 2. Modify 20.20.7.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.

1. Modify 20.20.1 [format.syn], header `<format>` synopsis, as indicated:

   >     […]
   >     // 20.20.7.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);
   >     […]

2. Modify 20.20.7.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 `typename Context::template formatter_type<Ti>` meets the Formatter requirements (20.20.6.1 [formatter.requirements]) for each `Ti` in `Args`.

   > > -3- Returns: An object of type `format-arg-store<Context, Args...>` whose `args` data member is initialized with `{basic_format_arg<Context>(fmt_args)...}`.