This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3631. `basic_format_arg(T&&)` should use `remove_cvref_t<T>` throughout

Section: 20.20.7.1 [format.arg] Status: New Submitter: Tim Song Opened: 2021-11-03 Last modified: 2021-11-06

Priority: 3

View all other issues in [format.arg].

View all issues with New status.

Discussion:

P2418R2 changed `basic_format_arg`'s constructor to take a forwarding reference but didn't change 20.20.7.1 [format.arg]/5 which inspects various properties of `T`. Now that the deduced type can be cvref-qualified, they need to be removed before the checks.

[2022-01-29; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4901.

1. Modify 20.20.7.1 [format.arg] as indicated:

   >     template<class T> explicit basic_format_arg(T&& v) noexcept;

   > > -?- Let `TD` be `remove_cvref_t<T>`.

   > > -4- Constraints: The template specialization

   > > >     typename Context::template formatter_type<remove_cvref_t<T>TD>

   > > meets the BasicFormatter requirements (20.20.6.1 [formatter.requirements]). The extent to which an implementation determines that the specialization meets the BasicFormatter requirements is unspecified, except that as a minimum the expression

   > > >     typename Context::template formatter_type<remove_cvref_t<T>TD>()
   > > >       .format(declval<T&>(), declval<Context&>())

   > > shall be well-formed when treated as an unevaluated operand (7.2.3 [expr.context]).

   > > -5- Effects:

   > > 1. (5.1) — if `TD` is `bool` or `char_type`, initializes `value` with `v`;

   > > 2. (5.2) — otherwise, if `TD` is `char` and `char_type` is `wchar_t`, initializes `value` with `static_cast<wchar_t>(v)`;

   > > 3. (5.3) — otherwise, if `TD` is a signed integer type (6.8.2 [basic.fundamental]) and `sizeof(TD) <= sizeof(int)`, initializes `value` with `static_cast<int>(v)`;

   > > 4. (5.4) — otherwise, if `TD` is an unsigned integer type and `sizeof(TD) <= sizeof(unsigned int)`, initializes `value` with `static_cast<unsigned int>(v)`;

   > > 5. (5.5) — otherwise, if `TD` is a signed integer type and `sizeof(TD) <= sizeof(long long int)`, initializes `value` with `static_cast<long long int>(v)`;

   > > 6. (5.6) — otherwise, if `TD` is an unsigned integer type and `sizeof(TD) <= sizeof(unsigned long long int)`, initializes `value` with `static_cast<unsigned long long int>(v)`;

   > > 7. (5.7) — otherwise, initializes `value` with `handle(v)`.