[format.context] # 28 Text processing library [[text]](./#text) ## 28.5 Formatting [[format]](format#context) ### 28.5.6 Formatter [[format.formatter]](format.formatter#format.context) #### 28.5.6.7 Class template basic_format_context [format.context] [🔗](#lib:basic_format_context) namespace std {templateclass basic_format_context { basic_format_args args_; // *exposition only* Out out_; // *exposition only* basic_format_context(const basic_format_context&) = delete; basic_format_context& operator=(const basic_format_context&) = delete; public:using iterator = Out; using char_type = charT; template using formatter_type = formatter; basic_format_arg arg(size_t id) const noexcept; std::locale locale(); iterator out(); void advance_to(iterator it); };} [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7704) An instance of basic_format_context holds formatting state consisting of the formatting arguments and the output iterator[.](#1.sentence-1) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7708) If a program declares an explicit or partial specialization ofbasic_format_context, the program is ill-formed, no diagnostic required[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7713) Out shall model [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10 Concept output_­iterator [iterator.concept.output]")[.](#3.sentence-1) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7716) 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[.](#4.sentence-1) Similarly, wformat_context is an alias for a specialization of basic_format_context with an output iterator that appends to wstring[.](#4.sentence-2) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7729) *Recommended practice*: For a given type charT, implementations should provide a single instantiation of basic_format_context for appending tobasic_string,vector, or any other container with contiguous storage by wrapping those in temporary objects with a uniform interface (such as a span) and polymorphic reallocation[.](#5.sentence-1) [🔗](#lib:arg,basic_format_context) `basic_format_arg arg(size_t id) const noexcept; ` [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7747) *Returns*: args_.get(id)[.](#6.sentence-1) [🔗](#lib:locale,basic_format_context) `std::locale locale(); ` [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7758) *Returns*: The locale passed to the formatting function if the latter takes one, and std​::​locale() otherwise[.](#7.sentence-1) [🔗](#lib:out,basic_format_context) `iterator out(); ` [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7771) *Effects*: Equivalent to: return std​::​move(out_); [🔗](#lib:advance_to,basic_format_context) `void advance_to(iterator it); ` [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L7782) *Effects*: Equivalent to: out_ = std​::​move(it); [*Example [1](#example-1)*: struct S { int value; }; template<> struct std::formatter { 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 is_digit = [](auto c) { return c >= '0' && c <= '9'; }; auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; }; if (get_char() != '{')return iter; ++iter; char c = get_char(); if (!is_digit(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) const {int width = ctx.arg(width_arg_id).visit([](auto value) -> int {if constexpr (!is_integral_v)throw format_error("width is not integral"); else if (value < 0 || value > numeric_limits::max())throw format_error("invalid width"); elsereturn value; }); 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*]