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.

### 3806. Should concept `formattable<T, charT>` default to `char`?

Section: 22.14.6.2 [format.formattable] Status: New Submitter: Jonathan Wakely Opened: 2022-10-28 Last modified: 2022-11-01

Priority: 2

View all issues with New status.

Discussion:

For many uses of `<format>` there's no need to explicitly mention the output type as `char`. There are either typedefs for `char` specializations (`format_context`, `format_parse_context`, `format_args`, etc.) or a default template argument (`formatter`, `range_formatter`). But for the new `formattable` concept you always need to specify the character type:

>     static_assert( std::formattable<int> ); // ill-formed
>     static_assert( std::formattable<int, char> ); // OK

Should the concept have a default template argument for the second parameter, to make it easier to check whether something is `formattable` as `char`?

[2022-11-01; Reflector poll]

Set priority to 2 after reflector poll. Two votes for NAD, the convenience makes it easier to misuse.

Proposed resolution:

This wording is relative to N4917.

1. Modify 22.14.1 [format.syn] as indicated:

   >     […]
   >     // 22.14.6 [format.formatter], formatter
   >     template<class T, class charT = char> struct formatter;

   >     // 22.14.6.2 [format.formattable], concept formattable
   >     template<class T, class charT = char>
   >       concept formattable = see below;
   >     […]

2. Modify 22.14.6.2 [format.formattable] as indicated:

   > [Drafting note: This repeats the default template argument already shown in the synopsis, which would not be valid in C++ code. That is consistent with our presentation style though, as this is not C++ code, it's a specification. See e.g. `indirect_strict_weak_order` and `subrange`.]

   > -1- Let `fmt-iter-for<charT>` be an unspecified type that models `output_iterator<const charT&>` (25.3.4.10 [iterator.concept.output]).

   > >     template<class T, class charT = char>
   > >       concept formattable =
   > >         semiregular<formatter<remove_cvref_t<T>, charT>> &&
   > >         requires(formatter<remove_cvref_t<T>, charT> f,
   > >                  const formatter<remove_cvref_t<T>, charT> cf,
   > >                  T t,
   > >                  basic_format_context<fmt-iter-for<charT>, charT> fc,
   > >                  basic_format_parse_context<charT> pc) {
   > >           { f.parse(pc) } -> same_as<basic_format_parse_context<charT>::iterator>;
   > >           { cf.format(t, fc) } -> same_as<fmt-iter-for<charT>>;
   > >         };