20 General utilities library [utilities]

20.20 Formatting [format]

20.20.1 Header <format> synopsis [format.syn]

namespace std {
  // [format.functions], formatting functions
  template<class... Args>
    string format(string_view fmt, const Args&... args);
  template<class... Args>
    wstring format(wstring_view fmt, const Args&... args);
  template<class... Args>
    string format(const locale& loc, string_view fmt, const Args&... args);
  template<class... Args>
    wstring format(const locale& loc, wstring_view fmt, const Args&... args);

  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);

  template<class Out, class... Args>
    Out format_to(Out out, string_view fmt, const Args&... args);
  template<class Out, class... Args>
    Out format_to(Out out, wstring_view fmt, const Args&... args);
  template<class Out, class... Args>
    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
  template<class Out, class... Args>
    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);

  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);

  template<class Out> struct format_to_n_result {
    Out out;
    iter_difference_t<Out> size;
  };
  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);

  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);

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

  // [format.parse.ctx], class template basic_­format_­parse_­context
  template<class charT> class basic_format_parse_context;
  using format_parse_context = basic_format_parse_context<char>;
  using wformat_parse_context = basic_format_parse_context<wchar_t>;

  template<class Out, class charT> class basic_format_context;
  using format_context = basic_format_context<unspecified, char>;
  using wformat_context = basic_format_context<unspecified, wchar_t>;

  // [format.arguments], arguments
  // [format.arg], class template basic_­format_­arg
  template<class Context> class basic_format_arg;

  template<class Visitor, class Context>
    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);

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

  template<class Context = format_context, class... Args>
    format-arg-store<Context, Args...>
      make_format_args(const Args&... args);
  template<class... Args>
    format-arg-store<wformat_context, Args...>
      make_wformat_args(const Args&... args);

  // [format.args], class template basic_­format_­args
  template<class Context> class basic_format_args;
  using format_args = basic_format_args<format_context>;
  using wformat_args = basic_format_args<wformat_context>;

  template<class Out, class charT>
    using format_args_t = basic_format_args<basic_format_context<Out, charT>>;

  // [format.error], class format_­error
  class format_error;
}

20.20.2 Format string [format.string]

20.20.2.1 In general [format.string.general]

A format string is a (possibly empty) sequence of replacement fields, escape sequences, and characters other than { and }.
Let charT be the character type of the format string.
Each character that is not part of a replacement field or an escape sequence is copied unchanged to the output.
An escape sequence is one of {{ or }}.
It is replaced with { or }, respectively, in the output.
The syntax of replacement fields is as follows:
replacement-field:
	{ arg-id format-specifier }
arg-id:
	0
	positive-integer
positive-integer:
	nonzero-digit
	positive-integer digit
nonnegative-integer:
	digit
	nonnegative-integer digit
nonzero-digit: one of
	1 2 3 4 5 6 7 8 9
digit: one of
	0 1 2 3 4 5 6 7 8 9
format-specifier:
	: format-spec
format-spec:
	as specified by the formatter specialization for the argument type
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.
The optional format-specifier field explicitly specifies a format for the replacement value.
Example
:
string s = format("{0}-{{", 8);         // value of s is "8-{"
— end example
 ]
If all arg-ids in a format string are omitted (including those in the format-spec, as interpreted by the corresponding formatter specialization), argument indices 0, 1, 2, … will automatically be used in that order.
If some arg-ids are omitted and some are present, the string is not a format string.
Note
:
A format string cannot contain a mixture of automatic and manual indexing.
— end note
 ]
Example
:
string s0 = format("{} to {}",   "a", "b"); // OK, automatic indexing
string s1 = format("{1} to {0}", "a", "b"); // OK, manual indexing
string s2 = format("{0} to {}",  "a", "b"); // not a format string (mixing automatic and manual indexing),
                                            // throws format_­error
string s3 = format("{} to {1}",  "a", "b"); // not a format string (mixing automatic and manual indexing),
                                            // throws format_­error
— end example
 ]
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.
Example
:
  • For arithmetic, pointer, and string types the format-spec is interpreted as a std-format-spec as described in ([format.string.std]).
  • For chrono types the format-spec is interpreted as a chrono-format-spec as described in ([time.format]).
  • For user-defined formatter specializations, the behavior of the parse member function determines how the format-spec is interpreted.
— end example
 ]

20.20.2.2 Standard format specifiers [format.string.std]

Each formatter specializations described in [format.formatter.spec] for fundamental and string types interprets format-spec as a std-format-spec.
Note
:
The format specification can be used to specify such details as field width, alignment, padding, and decimal precision.
Some of the formatting options are only supported for arithmetic types.
— end note
 ]
The syntax of format specifications is as follows:
std-format-spec:
	fill-and-align sign # 0 width precision type
fill-and-align:
	fill align
fill:
	any character other than { or }
align: one of
	< > ^
sign: one of
	+ - space
width:
	positive-integer
	{ arg-id }
precision:
	. nonnegative-integer
	. { arg-id }
type: one of
	a A b B c d e E f F g G n o p s x X
Note
:
The fill character can be any character other than { or }.
The presence of a fill character is signaled by the character following it, which must be one of the alignment options.
If the second character of std-format-spec is not a valid alignment option, then it is assumed that both the fill character and the alignment option are absent.
— end note
 ]
The meaning of the various alignment options is as specified in Table 57.
Example
:
char c = 120;
string s0 = format("{:6}", 42);         // value of s0 is "    42"
string s1 = format("{:6}", 'x');        // value of s1 is "x     "
string s2 = format("{:*<6}", 'x');      // value of s2 is "x*****"
string s3 = format("{:*>6}", 'x');      // value of s3 is "*****x"
string s4 = format("{:*^6}", 'x');      // value of s4 is "**x***"
string s5 = format("{:6d}", c);         // value of s5 is "   120"
string s6 = format("{:6}", true);       // value of s6 is "true  "
— end example
 ]
Note
:
Unless a minimum field width is defined, the field width is determined by the size of the content and the alignment option has no effect.
— end note
 ]
Table 57: Meaning of align options   [tab:format.align]
Option
Meaning
<
Forces the field to be left-aligned within the available space.
This is the default for non-arithmetic types, charT, and bool, unless an integer presentation type is specified.
>
Forces the field to be right-aligned within the available space.
This is the default for arithmetic types other than charT and bool or when an integer presentation type is specified.
^
Forces the field to be centered within the available space by inserting characters before and characters after the value, where n is the total number of fill characters to insert.
The sign option is only valid for arithmetic types other than charT and bool or when an integer presentation type is specified.
The meaning of the various options is as specified in Table 58.
Table 58: Meaning of sign options   [tab:format.sign]
Option
Meaning
+
Indicates that a sign should be used for both non-negative and negative numbers.
-
Indicates that a sign should be used only for negative numbers (this is the default behavior).
space
Indicates that a leading space should be used for non-negative numbers, and a minus sign for negative numbers.
The sign option applies to floating-point infinity and NaN.
Example
:
double inf = numeric_limits<double>::infinity();
double nan = numeric_limits<double>::quiet_NaN();
string s0 = format("{0:},{0:+},{0:-},{0: }", 1);        // value of s0 is "1,+1,1, 1"
string s1 = format("{0:},{0:+},{0:-},{0: }", -1);       // value of s1 is "-1,-1,-1,-1"
string s2 = format("{0:},{0:+},{0:-},{0: }", inf);      // value of s2 is "inf,+inf,inf, inf"
string s3 = format("{0:},{0:+},{0:-},{0: }", nan);      // value of s3 is "nan,+nan,nan, nan"
— end example
 ]
The # option causes the alternate form to be used for the conversion.
This option is only valid for arithmetic types other than charT and bool or when an integer presentation type is specified.
For integral types, the alternate form adds the base prefix (if any) specified in Table 60 to the output value.
For floating-point types, the alternate form causes the result of the conversion to always contain a decimal-point character, even if no digits follow it.
Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.
In addition, for g and G conversions, trailing zeros are not removed from the result.
The positive-integer in width is a decimal integer defining the minimum field width.
If width is not specified, there is no minimum field width, and the field width is determined based on the content of the field.
A zero (0) character preceding the width field pads the field with leading zeros (following any indication of sign or base) to the field width, except when applied to an infinity or NaN. This option is only valid for arithmetic types other than charT and bool or when an integer presentation type is specified.
If the 0 character and an align option both appear, the 0 character is ignored.
Example
:
char c = 120;
string s1 = format("{:+06d}", c);       // value of s1 is "+00120"
string s2 = format("{:#06x}", 0xa);     // value of s2 is "0x000a"
string s3 = format("{:<06}", -42);      // value of s3 is "-42   " (0 is ignored because of < alignment)
— end example
 ]
The nonnegative-integer in precision is a decimal integer defining the precision or maximum field size.
It can only be used with floating-point and string types.
For floating-point types this field specifies the formatting precision.
For string types it specifies how many characters will be used from the string.
The type determines how the data should be presented.
The available string presentation types are specified in Table 59.
Table 59: Meaning of type options for strings   [tab:format.type.string]
Type
Meaning
none, s
Copies the string to the output.
The meaning of some non-string presentation types is defined in terms of a call to to_­chars.
In such cases, let [first, last) be a range large enough to hold the to_­chars output and value be the formatting argument value.
Formatting is done as if by calling to_­chars as specified and copying the output through the output iterator of the format context.
Note
:
Additional padding and adjustments are performed prior to copying the output through the output iterator as specified by the format specifiers.
— end note
 ]
The available integer presentation types for integral types other than bool and charT are specified in Table 60.
Example
:
string s0 = format("{}", 42);                           // value of s0 is "42"
string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42);      // value of s1 is "101010 42 52 2a"
string s2 = format("{0:#x} {0:#X}", 42);                // value of s2 is "0x2a 0X2A"
string s3 = format("{:n}", 1234);                       // value of s3 might be "1,234"
                                                        // (depending on the locale)
— end example
 ]
Table 60: Meaning of type options for integer types   [tab:format.type.int]
Type
Meaning
b
to_­chars(first, last, value, 2); the base prefix is 0b.
B
The same as b, except that the base prefix is 0B.
c
Copies the character static_­cast<charT>(value) to the output.
Throws format_­error if value is not in the range of representable values for charT.
d
to_­chars(first, last, value).
o
to_­chars(first, last, value, 8); the base prefix is 0 if value is nonzero and is empty otherwise.
x
to_­chars(first, last, value, 16); the base prefix is 0x.
X
The same as x, except that it uses uppercase letters for digits above 9 and the base prefix is 0X.
n
The same as d, except that it uses the context's locale to insert the appropriate digit group separator characters.
none
The same as d.
Note
:
If the formatting argument type is charT or bool, the default is instead c or s, respectively.
— end note
 ]
The available charT presentation types are specified in Table 61.
Table 61: Meaning of type options for charT   [tab:format.type.char]
Type
Meaning
none, c
Copies the character to the output.
b, B, d, o, x, X, n
As specified in Table 60.
The available bool presentation types are specified in Table 62.
Table 62: Meaning of type options for bool   [tab:format.type.bool]
Type
Meaning
none, s
Copies textual representation, either true or false, to the output.
b, B, c, d, o, x, X, n
As specified in Table 60 for the value static_­cast<unsigned char>(value).
The available floating-point presentation types and their meanings for values other than infinity and NaN are specified in Table 63.
For lower-case presentation types, infinity and NaN are formatted as inf and nan, respectively.
For upper-case presentation types, infinity and NaN are formatted as INF and NAN, respectively.
Note
:
In either case, a sign is included if indicated by the sign option.
— end note
 ]
Table 63: Meaning of type options for floating-point types   [tab:format.type.float]
Type
Meaning
a
If precision is specified, equivalent to
to_chars(first, last, value, chars_format::hex, precision)
where precision is the specified formatting precision; equivalent to
to_chars(first, last, value, chars_format::hex)
otherwise.
A
The same as a, except that it uses uppercase letters for digits above 9 and P to indicate the exponent.
e
Equivalent to
to_chars(first, last, value, chars_format::scientific, precision)
where precision is the specified formatting precision, or 6 if precision is not specified.
E
The same as e, except that it uses E to indicate exponent.
f, F
Equivalent to
to_chars(first, last, value, chars_format::fixed, precision)
where precision is the specified formatting precision, or 6 if precision is not specified.
g
Equivalent to
to_chars(first, last, value, chars_format::general, precision)
where precision is the specified formatting precision, or 6 if precision is not specified.
G
The same as g, except that it uses E to indicate exponent.
n
The same as g, except that it uses the context's locale to insert the appropriate digit group and decimal radix separator characters.
none
If precision is specified, equivalent to
to_chars(first, last, value, chars_format::general, precision)
where precision is the specified formatting precision; equivalent to
to_chars(first, last, value)
otherwise.
The available pointer presentation types and their mapping to to_­chars are specified in Table 64.
Note
:
Pointer presentation types also apply to nullptr_­t.
— end note
 ]
Table 64: Meaning of type options for pointer types   [tab:format.type.ptr]
Type
Meaning
none, p
If uintptr_­t is defined,
to_chars(first, last, reinterpret_cast<uintptr_t>(value), 16)
with the prefix 0x added to the output; otherwise, implementation-defined.

20.20.3 Formatting functions [format.functions]

In the description of the functions, operator + is used for some of the iterator categories for which it does not have to be defined.
In these cases the semantics of a + n are the same as in [algorithms.requirements].
template<class... Args> string format(string_view fmt, const Args&... args);
Effects: Equivalent to:
return vformat(fmt, make_format_args(args...));
template<class... Args> wstring format(wstring_view fmt, const Args&... args);
Effects: Equivalent to:
return vformat(fmt, make_wformat_args(args...));
template<class... Args> string format(const locale& loc, string_view fmt, const Args&... args);
Effects: Equivalent to:
return vformat(loc, fmt, make_format_args(args...));
template<class... Args> wstring format(const locale& loc, wstring_view fmt, const Args&... args);
Effects: Equivalent to:
return vformat(loc, fmt, make_wformat_args(args...));
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);
Returns: A string object holding the character representation of formatting arguments provided by args formatted according to specifications given in fmt.
If present, loc is used for locale-specific formatting.
Throws: format_­error if fmt is not a format string.
template<class Out, class... Args> Out format_to(Out out, string_view fmt, const Args&... args); template<class Out, class... Args> Out format_to(Out out, wstring_view fmt, const Args&... args);
Effects: Equivalent to:
using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, fmt, {make_format_args<context>(args...)});
template<class Out, class... Args> Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args); template<class Out, class... Args> Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
Effects: Equivalent to:
using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, loc, fmt, {make_format_args<context>(args...)});
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);
Let charT be decltype(fmt)​::​value_­type.
Constraints: Out satisfies output_­iterator<const charT&>.
Preconditions: Out models output_­iterator<const charT&>.
Effects: Places the character representation of formatting the arguments provided by args, formatted according to the specifications given in fmt, into the range [out, out + N), where N is formatted_­size(fmt, args...) for the functions without a loc parameter and formatted_­size(loc, fmt, args...) for the functions with a loc parameter.
If present, loc is used for locale-specific formatting.
Returns: out + N.
Throws: format_­error if fmt is not a format string.
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);
Let
  • charT be decltype(fmt)​::​value_­type,
  • N be formatted_­size(fmt, args...) for the functions without a loc parameter and formatted_­size(loc, fmt, args...) for the functions with a loc parameter, and
  • M be clamp(n, 0, N).
Constraints: Out satisfies output_­iterator<const charT&>.
Preconditions: Out models output_­iterator<const charT&>, and formatter<, charT> meets the Formatter requirements ([formatter.requirements]) for each in Args.
Effects: Places the first M characters of the character representation of formatting the arguments provided by args, formatted according to the specifications given in fmt, into the range [out, out + M).
If present, loc is used for locale-specific formatting.
Returns: {out + M, N}.
Throws: format_­error if fmt is not a format string.
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);
Let charT be decltype(fmt)​::​value_­type.
Preconditions: formatter<, charT> meets the Formatter requirements ([formatter.requirements]) for each in Args.
Returns: The number of characters in the character representation of formatting arguments args formatted according to specifications given in fmt.
If present, loc is used for locale-specific formatting.
Throws: format_­error if fmt is not a format string.

20.20.4 Formatter [format.formatter]

20.20.4.1 Formatter requirements [formatter.requirements]

A type F meets the Formatter requirements if:
Given character type charT, output iterator type Out, and formatting argument type T, in Table 65:
  • f is a value of type F,
  • u is an lvalue of type T,
  • t is a value of a type convertible to (possibly const) T,
  • PC is basic_­format_­parse_­context<charT>,
  • FC is basic_­format_­context<Out, charT>,
  • pc is an lvalue of type PC, and
  • fc is an lvalue of type FC.
pc.begin() points to the beginning of the format-spec ([format.string]) of the replacement field being formatted in the format string.
If format-spec is empty then either pc.begin() == pc.end() or *pc.begin() == '}'.
Table 65: Formatter requirements   [tab:formatter]
Expression
Return type
Requirement
f.parse(pc)
PC​::​iterator
Parses format-spec ([format.string]) for type T in the range [pc.begin(), pc.end()) until the first unmatched character.
Throws format_­error unless the whole range is parsed or the unmatched character is }.
Note
:
This allows formatters to emit meaningful error messages.
— end note
 ]
Stores the parsed format specifiers in *this and returns an iterator past the end of the parsed range.
f.format(t, fc)
FC​::​iterator
Formats t according to the specifiers stored in *this, writes the output to fc.out() and returns an iterator past the end of the output range.
The output shall only depend on t, fc.locale(), and the range [pc.begin(), pc.end()) from the last call to f.parse(pc).
f.format(u, fc)
FC​::​iterator
As above, but does not modify u.

20.20.4.2 Formatter specializations [format.formatter.spec]

The functions defined in [format.functions] use specializations of the class template formatter to format individual arguments.
Let charT be either char or wchar_­t.
Each specialization of formatter is either enabled or disabled, as described below.
Note
:
Enabled specializations meet the Formatter requirements, and disabled specializations do not.
— end note
 ]
Each header that declares the template formatter provides the following enabled specializations:
  • The specializations
    template<> struct formatter<char, char>;
    template<> struct formatter<char, wchar_t>;
    template<> struct formatter<wchar_t, wchar_t>;
    
  • For each charT, the string type specializations
    template<> struct formatter<charT*, charT>;
    template<> struct formatter<const charT*, charT>;
    template<size_t N> struct formatter<const charT[N], charT>;
    template<class traits, class Allocator>
      struct formatter<basic_string<charT, traits, Allocator>, charT>;
    template<class traits>
      struct formatter<basic_string_view<charT, traits>, charT>;
    
  • For each charT, for each cv-unqualified arithmetic type ArithmeticT other than char, wchar_­t, char8_­t, char16_­t, or char32_­t, a specialization
    template<> struct formatter<ArithmeticT, charT>;
    
  • For each charT, the pointer type specializations
    template<> struct formatter<nullptr_t, charT>;
    template<> struct formatter<void*, charT>;
    template<> struct formatter<const void*, charT>;
    
The parse member functions of these formatters interpret the format specification as a std-format-spec as described in [format.string.std].
Note
:
Specializations such as formatter<wchar_­t, char> and formatter<const char*, wchar_­t> that would require implicit multibyte / wide string or character conversion are disabled.
— end note
 ]
For any types T and charT for which neither the library nor the user provides an explicit or partial specialization of the class template formatter, formatter<T, charT> is disabled.
If the library provides an explicit or partial specialization of formatter<T, charT>, that specialization is enabled except as noted otherwise.
If F is a disabled specialization of formatter, these values are false:
  • is_­default_­constructible_­v<F>,
  • is_­copy_­constructible_­v<F>,
  • is_­move_­constructible_­v<F>,
  • is_­copy_­assignable_­v<F>, and
  • is_­move_­assignable_­v<F>.
An enabled specialization formatter<T, charT> meets the Formatter requirements ([formatter.requirements]).
Example
:
#include <format>

enum color { red, green, blue };
const char* color_names[] = { "red", "green", "blue" };

template<> struct std::formatter<color> : std::formatter<const char*> {
  auto format(color c, format_context& ctx) {
    return formatter<const char*>::format(color_names[c], ctx);
  }
};

struct err {};

std::string s0 = std::format("{}", 42);         // OK, library-provided formatter
std::string s1 = std::format("{}", L"foo");     // ill-formed: disabled formatter
std::string s2 = std::format("{}", red);        // OK, user-provided formatter
std::string s3 = std::format("{}", err{});      // ill-formed: disabled formatter
— end example
 ]

20.20.4.3 Class template basic_­format_­parse_­context [format.parse.ctx]

namespace std {
  template<class charT>
  class basic_format_parse_context {
  public:
    using char_type = charT;
    using const_iterator = typename basic_string_view<charT>::const_iterator;
    using iterator = const_iterator;

  private:
    iterator begin_;                                    // exposition only
    iterator end_;                                      // exposition only
    enum indexing { unknown, manual, automatic };       // exposition only
    indexing indexing_;                                 // exposition only
    size_t next_arg_id_;                                // exposition only
    size_t num_args_;                                   // exposition only

  public:
    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
                                                  size_t num_args = 0) noexcept;
    basic_format_parse_context(const basic_format_parse_context&) = delete;
    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;

    constexpr const_iterator begin() const noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr void advance_to(const_iterator it);

    constexpr size_t next_arg_id();
    constexpr void check_arg_id(size_t id);
  };
}
An instance of basic_­format_­parse_­context holds the format string parsing state consisting of the format string range being parsed and the argument counter for automatic indexing.
constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt, size_t num_args = 0) noexcept;
Effects: Initializes begin_­ with fmt.begin(), end_­ with fmt.end(), indexing_­ with unknown, next_­arg_­id_­ with 0, and num_­args_­ with num_­args.
constexpr const_iterator begin() const noexcept;
Returns: begin_­.
constexpr const_iterator end() const noexcept;
Returns: end_­.
constexpr void advance_to(const_iterator it);
Preconditions: end() is reachable from it.
Effects: Equivalent to: begin_­ = it;
constexpr size_t next_arg_id();
Effects: If indexing_­ != manual, equivalent to:
if (indexing_ == unknown)
  indexing_ = automatic;
return next_arg_id_++;
Throws: format_­error if indexing_­ == manual which indicates mixing of automatic and manual argument indexing.
constexpr void check_arg_id(size_t id);
Effects: If indexing_­ != automatic, equivalent to:
if (indexing_ == unknown)
  indexing_ = manual;
Throws: format_­error if indexing_­ == automatic which indicates mixing of automatic and manual argument indexing.
Remarks: Call expressions where id >= num_­args_­ are not core constant expressions ([expr.const]).

20.20.4.4 Class template basic_­format_­context [format.context]

namespace std {
  template<class Out, class charT>
  class basic_format_context {
    basic_format_args<basic_format_context> args_;      // exposition only
    Out out_;                                           // exposition only

  public:
    using iterator = Out;
    using char_type = charT;
    template<class T> using formatter_type = formatter<T, charT>;

    basic_format_arg<basic_format_context> arg(size_t id) const;
    std::locale locale();

    iterator out();
    void advance_to(iterator it);
  };
}
An instance of basic_­format_­context holds formatting state consisting of the formatting arguments and the output iterator.
Out shall model output_­iterator<const charT&>.
format_­context is an alias for a specialization of basic_­format_­context with an output iterator that appends to string, such as back_­insert_­iterator<string>.
Similarly, wformat_­context is an alias for a specialization of basic_­format_­context with an output iterator that appends to wstring.
Note
:
For a given type charT, implementations are encouraged to provide a single instantiation of basic_­format_­context for appending to basic_­string<charT>, vector<charT>, or any other container with contiguous storage by wrapping those in temporary objects with a uniform interface (such as a span<charT>) and polymorphic reallocation.
— end note
 ]
basic_format_arg<basic_format_context> arg(size_t id) const;
Returns: args_­.get(id).
std::locale locale();
Returns: The locale passed to the formatting function if the latter takes one, and std​::​locale() otherwise.
iterator out();
Returns: out_­.
void advance_to(iterator it);
Effects: Equivalent to: out_­ = it;
Example
:
struct S { int value; };

template<> struct std::formatter<S> {
  size_t width_arg_id = 0;

  // Parses a width argument id in the format { digit }.
  constexpr auto parse(format_parse_context& ctx) {
    auto iter = ctx.begin();
    auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; };
    if (get_char() != '{')
      return iter;
    ++iter;
    char c = get_char();
    if (!isdigit(c) || (++iter, get_char()) != '}')
      throw format_error("invalid format");
    width_arg_id = c - '0';
    ctx.check_arg_id(width_arg_id);
    return ++iter;
  }

  // Formats an S with width given by the argument width_­arg_­id.
  auto format(S s, format_context& ctx) {
    int width = visit_format_arg([](auto value) -> int {
      if constexpr (!is_integral_v<decltype(value)>)
        throw format_error("width is not integral");
      else if (value < 0 || value > numeric_limits<int>::max())
        throw format_error("invalid width");
      else
        return value;
      }, ctx.arg(width_arg_id));
    return format_to(ctx.out(), "{0:x<{1}}", s.value, width);
  }
};

std::string s = std::format("{0:{1}}", S{42}, 10);  // value of s is "xxxxxxxx42"
— end example
 ]

20.20.5 Arguments [format.arguments]

20.20.5.1 Class template basic_­format_­arg [format.arg]

namespace std {
  template<class Context>
  class basic_format_arg {
  public:
    class handle;

  private:
    using char_type = typename Context::char_type;                              // exposition only

    variant<monostate, bool, char_type,
            int, unsigned int, long long int, unsigned long long int,
            float, double, long double,
            const char_type*, basic_string_view<char_type>,
            const void*, handle> value;                                         // exposition only

    template<class T> explicit basic_format_arg(const T& v) noexcept;           // exposition only
    explicit basic_format_arg(float n) noexcept;                                // exposition only
    explicit basic_format_arg(double n) noexcept;                               // exposition only
    explicit basic_format_arg(long double n) noexcept;                          // exposition only
    explicit basic_format_arg(const char_type* s);                              // exposition only

    template<class traits>
      explicit basic_format_arg(
        basic_string_view<char_type, traits> s) noexcept;                       // exposition only

    template<class traits, class Allocator>
      explicit basic_format_arg(
        const basic_string<char_type, traits, Allocator>& s) noexcept;          // exposition only

    explicit basic_format_arg(nullptr_t) noexcept;                              // exposition only

    template<class T>
      explicit basic_format_arg(const T* p) noexcept;                           // exposition only

    template<class Visitor, class Ctx>
      friend auto visit_format_arg(Visitor&& vis,
                                   basic_format_arg<Ctx> arg);                  // exposition only

    template<class Ctx, class... Args>
      friend format-arg-store<Ctx, Args...>
        make_format_args(const Args&... args);                                  // exposition only

  public:
    basic_format_arg() noexcept;

    explicit operator bool() const noexcept;
  };
}
An instance of basic_­format_­arg provides access to a formatting argument for user-defined formatters.
The behavior of a program that adds specializations of basic_­format_­arg is undefined.
basic_format_arg() noexcept;
Postconditions: !(*this).
template<class T> explicit basic_format_arg(const T& v) noexcept;
Constraints: The template specialization
typename Context::template formatter_type<T>
is an enabled specialization of formatter ([format.formatter]).
The extent to which an implementation determines that the specialization is enabled is unspecified, except that as a minimum the expression
typename Context::template formatter_type<T>()
  .format(declval<const T&>(), declval<Context&>())
shall be well-formed when treated as an unevaluated operand.
Effects:
  • if T is bool or char_­type, initializes value with v; otherwise,
  • if T is char and char_­type is wchar_­t, initializes value with static_­cast<wchar_­t>(v); otherwise,
  • if T is a signed integer type ([basic.fundamental]) and sizeof(T) <= sizeof(int), initializes value with static_­cast<int>(v); otherwise,
  • if T is an unsigned integer type and sizeof(T) <= sizeof(unsigned int), initializes value with static_­cast<unsigned int>(v); otherwise,
  • if T is a signed integer type and sizeof(T) <= sizeof(long long int), initializes value with static_­cast<long long int>(v); otherwise,
  • if T is an unsigned integer type and sizeof(T) <= sizeof(unsigned long long int), initializes value with static_­cast<unsigned long long int>(v); otherwise,
  • initializes value with handle(v).
explicit basic_format_arg(float n) noexcept; explicit basic_format_arg(double n) noexcept; explicit basic_format_arg(long double n) noexcept;
Effects: Initializes value with n.
explicit basic_format_arg(const char_type* s);
Preconditions: s points to a NTCTS ([defns.ntcts]).
Effects: Initializes value with s.
template<class traits> explicit basic_format_arg(basic_string_view<char_type, traits> s) noexcept;
Effects: Initializes value with s.
template<class traits, class Allocator> explicit basic_format_arg( const basic_string<char_type, traits, Allocator>& s) noexcept;
Effects: Initializes value with basic_­string_­view<char_­type>(s.data(), s.size()).
explicit basic_format_arg(nullptr_t) noexcept;
Effects: Initializes value with static_­cast<const void*>(nullptr).
template<class T> explicit basic_format_arg(T* p) noexcept;
Constraints: is_­void_­v<T> is true.
Effects: Initializes value with p.
Note
:
Constructing basic_­format_­arg from a pointer to a member is ill-formed unless the user provides an enabled specialization of formatter for that pointer to member type.
— end note
 ]
explicit operator bool() const noexcept;
Returns: !holds_­alternative<monostate>(value).
The class handle allows formatting an object of a user-defined type.
namespace std {
  template<class Context>
  class basic_format_arg<Context>::handle {
    const void* ptr_;                                           // exposition only
    void (*format_)(basic_format_parse_context<char_type>&,
                    Context&, const void*);                     // exposition only

    template<class T> explicit handle(const T& val) noexcept;   // exposition only

    friend class basic_format_arg<Context>;                     // exposition only

  public:
    void format(basic_format_parse_context<char_type>&, Context& ctx) const;
  };
}
template<class T> explicit handle(const T& val) noexcept;
Effects: Initializes ptr_­ with addressof(val) and format_­ with
[](basic_format_parse_context<char_type>& parse_ctx,
   Context& format_ctx, const void* ptr) {
  typename Context::template formatter_type<T> f;
  parse_ctx.advance_to(f.parse(parse_ctx));
  format_ctx.advance_to(f.format(*static_cast<const T*>(ptr), format_ctx));
}
void format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const;
Effects: Equivalent to: format_­(parse_­ctx, format_­ctx, ptr_­);
template<class Visitor, class Context> see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
Effects: Equivalent to: return visit(forward<Visitor>(vis), arg.value);

20.20.5.2 Class template format-arg-store [format.arg.store]

namespace std {
  template<class Context, class... Args>
  struct format-arg-store {      // exposition only
    array<basic_format_arg<Context>, sizeof...(Args)> args;
  };
}
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&... args);
Preconditions: The type typename Context​::​template formatter_­type<> meets the Formatter requirements ([formatter.requirements]) for each in Args.
Returns: {basic_­format_­arg<Context>(args)...}.
template<class... Args> format-arg-store<wformat_context, Args...> make_wformat_args(const Args&... args);
Effects: Equivalent to: return make_­format_­args<wformat_­context>(args...);

20.20.5.3 Class template basic_­format_­args [format.args]

namespace std {
  template<class Context>
  class basic_format_args {
    size_t size_;                               // exposition only
    const basic_format_arg<Context>* data_;     // exposition only

  public:
    basic_format_args() noexcept;

    template<class... Args>
      basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;

    basic_format_arg<Context> get(size_t i) const noexcept;
  };
}
An instance of basic_­format_­args provides access to formatting arguments.
basic_format_args() noexcept;
Effects: Initializes size_­ with 0.
template<class... Args> basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
Effects: Initializes size_­ with sizeof...(Args) and data_­ with store.args.data().
basic_format_arg<Context> get(size_t i) const noexcept;
Returns: i < size_­ ? data_­[i] : basic_­format_­arg<Context>().
Note
:
Implementations are encouraged to optimize the representation of basic_­format_­args for small number of formatting arguments by storing indices of type alternatives separately from values and packing the former.
— end note
 ]

20.20.6 Class format_­error [format.error]

namespace std {
  class format_error : public runtime_error {
  public:
    explicit format_error(const string& what_arg);
    explicit format_error(const char* what_arg);
  };
}
The class format_­error defines the type of objects thrown as exceptions to report errors from the formatting library.
format_error(const string& what_arg);
Postconditions: strcmp(what(), what_­arg.c_­str()) == 0.
format_error(const char* what_arg);
Postconditions: strcmp(what(), what_­arg) == 0.