[format.tuple] # 28 Text processing library [[text]](./#text) ## 28.5 Formatting [[format]](format#tuple) ### 28.5.9 Tuple formatter [format.tuple] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8755) For each of pair and tuple, the library provides the following formatter specialization where *pair-or-tuple* is the name of the template: [🔗](#lib:formatter) namespace std {template... Ts>struct formatter<*pair-or-tuple*, charT> {private: tuple, charT>...> *underlying_*; // *exposition only* basic_string_view *separator_* = *STATICALLY-WIDEN*(", "); // *exposition only* basic_string_view *opening-bracket_* = *STATICALLY-WIDEN*("("); // *exposition only* basic_string_view *closing-bracket_* = *STATICALLY-WIDEN*(")"); // *exposition only*public:constexpr void set_separator(basic_string_view sep) noexcept; constexpr void set_brackets(basic_string_view opening, basic_string_view closing) noexcept; templateconstexpr typename ParseContext::iterator parse(ParseContext& ctx); templatetypename FormatContext::iterator format(*see below*& elems, FormatContext& ctx) const; }; templateconstexpr bool enable_nonlocking_formatter_optimization<*pair-or-tuple*> =(enable_nonlocking_formatter_optimization && ...);} [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8791) The parse member functions of these formatters interpret the format specification as a *tuple-format-spec* according to the following syntax: tuple-format-spec : tuple-fill-and-alignopt widthopt tuple-typeopt tuple-fill-and-align : tuple-fillopt align tuple-fill : any character other than { or } or : tuple-type : m n [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8817) The *tuple-fill-and-align* is interpreted the same way as a *fill-and-align* ([[format.string.std]](format.string.std "28.5.2.2 Standard format specifiers"))[.](#3.sentence-1) The productions *align* and *width* are described in [[format.string]](format.string "28.5.2 Format string")[.](#3.sentence-2) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8823) The *tuple-type* specifier changes the way a pair or tuple is formatted, with certain options only valid with certain argument types[.](#4.sentence-1) The meaning of the various type options is as specified in Table [116](#tab:formatter.tuple.type "Table 116: Meaning of tuple-type options")[.](#4.sentence-2) Table [116](#tab:formatter.tuple.type) — Meaning of *tuple-type* options [[tab:formatter.tuple.type]](./tab:formatter.tuple.type) | [🔗](#tab:formatter.tuple.type-row-1)
**Option** | **Requirements** | **Meaning** | | --- | --- | --- | | [🔗](#tab:formatter.tuple.type-row-2)
m | sizeof...(Ts) == 2 | Equivalent to: set_separator(*STATICALLY-WIDEN*(": ")); set_brackets({}, {}); | | [🔗](#tab:formatter.tuple.type-row-3)
n | none | Equivalent to: set_brackets({}, {}); | | [🔗](#tab:formatter.tuple.type-row-4)
none | none | No effects | [🔗](#lib:set_separator,formatter) `constexpr void set_separator(basic_string_view sep) noexcept; ` [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8861) *Effects*: Equivalent to: *separator_* = sep; [🔗](#lib:set_brackets,formatter) `constexpr void set_brackets(basic_string_view opening, basic_string_view closing) noexcept; ` [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8873) *Effects*: Equivalent to:*opening-bracket_* = opening;*closing-bracket_* = closing; [🔗](#lib:parse,formatter) `template constexpr typename ParseContext::iterator parse(ParseContext& ctx); ` [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8890) *Effects*: Parses the format specifiers as a *tuple-format-spec* and stores the parsed specifiers in *this[.](#7.sentence-1) The values of*opening-bracket_*,*closing-bracket_*, and*separator_* are modified if and only if required by the *tuple-type*, if present[.](#7.sentence-2) For each element *e* in *underlying_*, calls *e*.parse(ctx) to parse an empty *format-spec* and, if *e*.set_debug_format() is a valid expression, calls *e*.set_debug_format()[.](#7.sentence-3) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8906) *Returns*: An iterator past the end of the *tuple-format-spec*[.](#8.sentence-1) [🔗](#lib:format,formatter) `template typename FormatContext::iterator format(see below& elems, FormatContext& ctx) const; ` [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8919) The type of elems is: - [(9.1)](#9.1) If ([formattable](format.formattable#concept:formattable "28.5.6.3 Concept formattable [format.formattable]") && ...) is true,const *pair-or-tuple*&[.](#9.1.sentence-1) - [(9.2)](#9.2) Otherwise *pair-or-tuple*&[.](#9.2.sentence-1) [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8929) *Effects*: Writes the following into ctx.out(), adjusted according to the *tuple-format-spec*: - [(10.1)](#10.1) *opening-bracket_*, - [(10.2)](#10.2) for each index I in the [0, sizeof...(Ts)): * [(10.2.1)](#10.2.1) if I != 0, *separator_*, * [(10.2.2)](#10.2.2) the result of writing get(elems) via get(*underlying_*), and - [(10.3)](#10.3) *closing-bracket_*[.](#10.sentence-1) [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L8949) *Returns*: An iterator past the end of the output range[.](#11.sentence-1)