[format.arguments]

# 28 Text processing library [[text]](./#text)

## 28.5 Formatting [[format]](format#arguments)

### 28.5.8 Arguments [format.arguments]

#### [28.5.8.1](#format.arg) Class template basic_format_arg [[format.arg]](format.arg)

[ð](#lib:basic_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(T& v) noexcept; // *exposition only*public: basic_format_arg() noexcept; explicit operator bool() const noexcept; template<class Visitor>decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); template<class R, class Visitor> R visit(this basic_format_arg arg, Visitor&& vis); };}

[1](#format.arg-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8454)

An instance of basic_format_arg provides access to
a formatting argument for user-defined formatters[.](#format.arg-1.sentence-1)

[2](#format.arg-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8458)

The behavior of a program that adds specializations ofbasic_format_arg is undefined[.](#format.arg-2.sentence-1)

[ð](#lib:basic_format_arg,constructor)

`basic_format_arg() noexcept;
`

[3](#format.arg-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8468)

*Postconditions*: !(*this)[.](#format.arg-3.sentence-1)

[ð](#format.arg-itemdecl:2)

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

[4](#format.arg-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8478)

*Constraints*: T satisfies [*formattable-with*](format.formattable#concept:formattable-with "28.5.6.3 Concept formattable [format.formattable]")<Context>[.](#format.arg-4.sentence-1)

[5](#format.arg-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8482)

*Preconditions*: If decay_t<T> is char_type* or const char_type*,static_cast<const char_  
type*>(v) points to an NTCTS ([[defns.ntcts]](defns.ntcts "3.36 NTCTS"))[.](#format.arg-5.sentence-1)

[6](#format.arg-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8487)

*Effects*: Let TD be remove_const_t<T>[.](#format.arg-6.sentence-1)

- [(6.1)](#format.arg-6.1)

If TD is bool or char_type,
initializes value with v;

- [(6.2)](#format.arg-6.2)

otherwise, if TD is char and char_type iswchar_t, initializes value withstatic_cast<wchar_t>(static_cast<unsigned char>(v));

- [(6.3)](#format.arg-6.3)

otherwise, if TD is a signed integer type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))
and sizeof(TD) <= sizeof(int),
initializes value with static_cast<int>(v);

- [(6.4)](#format.arg-6.4)

otherwise, if TD is an unsigned integer type andsizeof(TD) <= sizeof(unsigned int), initializesvalue with static_cast<unsigned int>(v);

- [(6.5)](#format.arg-6.5)

otherwise, if TD is a signed integer type andsizeof(TD) <= sizeof(long long int), initializesvalue with static_cast<long long int>(v);

- [(6.6)](#format.arg-6.6)

otherwise, if TD is an unsigned integer type andsizeof(TD) <= sizeof(unsigned long long int), initializesvalue withstatic_cast<unsigned long long int>(v);

- [(6.7)](#format.arg-6.7)

otherwise, if TD is a standard floating-point type,
initializes value with v;

- [(6.8)](#format.arg-6.8)

otherwise, if TD is
a specialization of basic_string_view or basic_string andTD​::​value_type is char_type,
initializes value withbasic_string_view<char_type>(v.data(), v.size());

- [(6.9)](#format.arg-6.9)

otherwise, if decay_t<TD> ischar_type* or const char_type*,
initializes value with static_cast<const char_type*>(v);

- [(6.10)](#format.arg-6.10)

otherwise, if is_void_v<remove_pointer_t<TD>> is true oris_null_pointer_v<TD> is true,
initializes value with static_cast<const void*>(v);

- [(6.11)](#format.arg-6.11)

otherwise, initializes value with handle(v).

[*Note [1](#format.arg-note-1)*:

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[.](#format.arg-6.sentence-2)

â *end note*]

[ð](#lib:operator_bool,basic_format_arg)

`explicit operator bool() const noexcept;
`

[7](#format.arg-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8550)

*Returns*: !holds_alternative<monostate>(value)[.](#format.arg-7.sentence-1)

[ð](#lib:visit,basic_format_arg)

`template<class Visitor>
  decltype(auto) visit(this basic_format_arg arg, Visitor&& vis);
`

[8](#format.arg-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8562)

*Effects*: Equivalent to: return arg.value.visit(std​::​forward<Visitor>(vis));

[ð](#lib:visit,basic_format_arg_)

`template<class R, class Visitor>
  R visit(this basic_format_arg arg, Visitor&& vis);
`

[9](#format.arg-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8574)

*Effects*: Equivalent to: return arg.value.visit<R>(std​::​forward<Visitor>(vis));

[10](#format.arg-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8579)

The class handle allows formatting an object of a user-defined type[.](#format.arg-10.sentence-1)

[ð](#lib:basic_format_arg::handle)

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(T& val) noexcept; // *exposition only*public:void format(basic_format_parse_context<char_type>&, Context& ctx) const; };}

[ð](#lib:basic_format_arg::handle,constructor)

`template<class T> explicit handle(T& val) noexcept;
`

[11](#format.arg-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8606)

Let

- [(11.1)](#format.arg-11.1)

TD be remove_const_t<T>,

- [(11.2)](#format.arg-11.2)

TQ be const TD ifconst TD satisfies [*formattable-with*](format.formattable#concept:formattable-with "28.5.6.3 Concept formattable [format.formattable]")<Context> and TD otherwise[.](#format.arg-11.sentence-1)

[12](#format.arg-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8617)

*Mandates*: TQ satisfies [*formattable-with*](format.formattable#concept:formattable-with "28.5.6.3 Concept formattable [format.formattable]")<Context>[.](#format.arg-12.sentence-1)

[13](#format.arg-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8621)

*Effects*: Initializesptr_ with addressof(val) andformat_ with[](basic_format_parse_context<char_type>& parse_ctx,
 Context& format_ctx, const void* ptr) {typename Context::template formatter_type<TD> f;
 parse_ctx.advance_to(f.parse(parse_ctx));
 format_ctx.advance_to(f.format(*const_cast<TQ*>(static_cast<const TD*>(ptr)),
 format_ctx));}

[ð](#lib:format,basic_format_arg::handle)

`void format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const;
`

[14](#format.arg-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8643)

*Effects*: Equivalent to: format_(parse_ctx, format_ctx, ptr_);

#### [28.5.8.2](#format.arg.store) Class template *format-arg-store* [[format.arg.store]](format.arg.store)

namespace std {template<class Context, class... Args>class *format-arg-store* { // *exposition only* array<basic_format_arg<Context>, sizeof...(Args)> *args*; // *exposition only*};}

[1](#format.arg.store-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8659)

An instance of *format-arg-store* stores formatting arguments[.](#format.arg.store-1.sentence-1)

[ð](#lib:make_format_args)

`template<class Context = format_context, class... Args>
  format-arg-store<Context, Args...> make_format_args(Args&... fmt_args);
`

[2](#format.arg.store-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8669)

*Preconditions*: The typetypename Context​::​template formatter_type<remove_const_t<Ti>>  
 meets the *BasicFormatter* requirements ([[formatter.requirements]](formatter.requirements "28.5.6.1 Formatter requirements"))
for each Ti in Args[.](#format.arg.store-2.sentence-1)

[3](#format.arg.store-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8676)

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

[ð](#lib:make_wformat_args)

`template<class... Args>
  format-arg-store<wformat_context, Args...> make_wformat_args(Args&... args);
`

[4](#format.arg.store-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8690)

*Effects*: Equivalent to:return make_format_args<wformat_context>(args...);

#### [28.5.8.3](#format.args) Class template basic_format_args [[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:template<class... Args> basic_format_args(const *format-arg-store*<Context, Args...>& store) noexcept;

 basic_format_arg<Context> get(size_t i) const noexcept; }; template<class Context, class... Args> basic_format_args(*format-arg-store*<Context, Args...>) -> basic_format_args<Context>;}

[1](#format.args-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8717)

An instance of basic_format_args provides access to formatting
arguments[.](#format.args-1.sentence-1)

Implementations should
optimize the representation of basic_format_args for a small number of formatting arguments[.](#format.args-1.sentence-2)

[*Note [1](#format.args-note-1)*:

For example, by storing indices of type alternatives separately from values
and packing the former[.](#format.args-1.sentence-3)

â *end note*]

[ð](#lib:basic_format_args,constructor)

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

[2](#format.args-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8735)

*Effects*: Initializessize_ with sizeof...(Args) anddata_ with store.args.data()[.](#format.args-2.sentence-1)

[ð](#lib:get,basic_format_args)

`basic_format_arg<Context> get(size_t i) const noexcept;
`

[3](#format.args-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8748)

*Returns*: i < size_ ? data_[i] : basic_format_arg<Context>()[.](#format.args-3.sentence-1)
