[format.range.formatter]

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

## 28.5 Formatting [[format]](format#range.formatter)

### 28.5.7 Formatting of ranges [[format.range]](format.range#formatter)

#### 28.5.7.2 Class template range_formatter [format.range.formatter]

[ð](#lib:range_formatter)

namespace std {template<class T, class charT = char>requires [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<T>, T> && [formattable](format.formattable#concept:formattable "28.5.6.3 Concept formattable [format.formattable]")<T, charT>class range_formatter { formatter<T, charT> *underlying_*; // *exposition only* basic_string_view<charT> *separator_* = *STATICALLY-WIDEN*<charT>(", "); // *exposition only* basic_string_view<charT> *opening-bracket_* = *STATICALLY-WIDEN*<charT>("["); // *exposition only* basic_string_view<charT> *closing-bracket_* = *STATICALLY-WIDEN*<charT>("]"); // *exposition only*public:constexpr void set_separator(basic_string_view<charT> sep) noexcept; constexpr void set_brackets(basic_string_view<charT> opening,
 basic_string_view<charT> closing) noexcept; constexpr formatter<T, charT>& underlying() noexcept { return *underlying_*; }constexpr const formatter<T, charT>& underlying() const noexcept { return *underlying_*; }template<class ParseContext>constexpr typename ParseContext::iterator
 parse(ParseContext& ctx); template<ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class FormatContext>requires [formattable](format.formattable#concept:formattable "28.5.6.3 Concept formattable [format.formattable]")<ranges::range_reference_t<R>, charT> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<ranges::range_reference_t<R>>, T>typename FormatContext::iterator
 format(R&& r, FormatContext& ctx) const; };}

[1](#1)

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

The class template range_formatter is a utility
for implementing formatter specializations for range types[.](#1.sentence-1)

[2](#2)

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

range_formatter interprets *format-spec* as a *range-format-spec*[.](#2.sentence-1)

The syntax of format specifications is as follows:

range-format-spec :  
range-fill-and-alignopt widthopt nopt range-typeopt range-underlying-specopt

range-fill-and-align :  
range-fillopt align

range-fill :  
any character other than { or } or :

range-type :  
m  
s  
?s

range-underlying-spec :  
: format-spec

[3](#3)

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

For range_formatter<T, charT>,
the *format-spec* in a *range-underlying-spec*, if any,
is interpreted by formatter<T, charT>[.](#3.sentence-1)

[4](#4)

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

The *range-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"))[.](#4.sentence-1)

The productions *align* and *width* are described in [[format.string]](format.string "28.5.2 Format string")[.](#4.sentence-2)

[5](#5)

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

The n option causes the range to be formatted
without the opening and closing brackets[.](#5.sentence-1)

[*Note [1](#note-1)*:

This is equivalent to invoking set_brackets({}, {})[.](#5.sentence-2)

â *end note*]

[6](#6)

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

The *range-type* specifier changes the way a range is formatted,
with certain options only valid with certain argument types[.](#6.sentence-1)

The meaning of the various type options
is as specified in Table [115](#tab:formatter.range.type "Table 115: Meaning of range-type options")[.](#6.sentence-2)

Table [115](#tab:formatter.range.type) — Meaning of *range-type* options [[tab:formatter.range.type]](./tab:formatter.range.type)  

| [ð](#tab:formatter.range.type-row-1)<br>**Option** | **Requirements** | **Meaning** |
| --- | --- | --- |
| [ð](#tab:formatter.range.type-row-2)<br>m | T shall be either a specialization of pair or a specialization of tuple such that tuple_size_v<T> is 2[.](#tab:formatter.range.type-row-2-column-2-sentence-1) | Indicates that the opening bracket should be "{", the closing bracket should be "}", the separator should be ", ", and each range element should be formatted as if m were specified for its *tuple-type*[.](#tab:formatter.range.type-row-2-column-3-sentence-1)<br>[*Note [2](#tab:formatter.range.type-row-2-column-3-note-2)*:<br>If the n option is provided in addition to the m option, both the opening and closing brackets are still empty[.](#tab:formatter.range.type-row-2-column-3-sentence-2) â *end note*] |
| [ð](#tab:formatter.range.type-row-3)<br>s | T shall be charT[.](#tab:formatter.range.type-row-3-column-2-sentence-1) | Indicates that the range should be formatted as a string[.](#tab:formatter.range.type-row-3-column-3-sentence-1) |
| [ð](#tab:formatter.range.type-row-4)<br>?s | T shall be charT[.](#tab:formatter.range.type-row-4-column-2-sentence-1) | Indicates that the range should be formatted as an escaped string ([[format.string.escaped]](format.string.escaped "28.5.6.5 Formatting escaped characters and strings"))[.](#tab:formatter.range.type-row-4-column-3-sentence-1) |

If the *range-type* is s or ?s,
then there shall be
no n option and no *range-underlying-spec*[.](#6.sentence-3)

[ð](#lib:set_separator,range_formatter)

`constexpr void set_separator(basic_string_view<charT> sep) noexcept;
`

[7](#7)

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

*Effects*: Equivalent to: *separator_* = sep;

[ð](#lib:set_brackets,range_formatter)

`constexpr void set_brackets(basic_string_view<charT> opening,
                            basic_string_view<charT> closing) noexcept;
`

[8](#8)

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

*Effects*: Equivalent to:*opening-bracket_* = opening;*closing-bracket_* = closing;

[ð](#lib:parse,range_formatter)

`template<class ParseContext>
  constexpr typename ParseContext::iterator
    parse(ParseContext& ctx);
`

[9](#9)

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

*Effects*: Parses the format specifiers as a *range-format-spec* and
stores the parsed specifiers in *this[.](#9.sentence-1)

Calls *underlying_*.parse(ctx) to parse*format-spec* in *range-format-spec* or,
if the latter is not present, an empty *format-spec*[.](#9.sentence-2)

The values of*opening-bracket_*, *closing-bracket_*, and *separator_* are modified if and only if required by
the *range-type* or the n option, if present[.](#9.sentence-3)

If:

- [(9.1)](#9.1)

the *range-type* is neither s nor ?s,

- [(9.2)](#9.2)

*underlying_*.set_debug_format() is a valid expression, and

- [(9.3)](#9.3)

there is no *range-underlying-spec*,

then calls *underlying_*.set_debug_format()[.](#9.sentence-4)

[10](#10)

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

*Returns*: An iterator past the end of the *range-format-spec*[.](#10.sentence-1)

[ð](#lib:format,range_formatter)

`template<ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class FormatContext>
    requires [formattable](format.formattable#concept:formattable "28.5.6.3 Concept formattable [format.formattable]")<ranges::range_reference_t<R>, charT> &&
             [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<ranges::range_reference_t<R>>, T>
  typename FormatContext::iterator
    format(R&& r, FormatContext& ctx) const;
`

[11](#11)

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

*Effects*: Writes the following into ctx.out(),
adjusted according to the *range-format-spec*:

- [(11.1)](#11.1)

  If the *range-type* was s,
then as if by formatting basic_string<charT>(from_range, r)[.](#11.1.sentence-1)

- [(11.2)](#11.2)

  Otherwise, if the *range-type* was ?s,
then as if by formatting basic_string<charT>(from_range, r) as an escaped string ([[format.string.escaped]](format.string.escaped "28.5.6.5 Formatting escaped characters and strings"))[.](#11.2.sentence-1)

- [(11.3)](#11.3)

  Otherwise,
  * [(11.3.1)](#11.3.1)

*opening-bracket_*,

  * [(11.3.2)](#11.3.2)

for each element e of the range r:
    +
          [(11.3.2.1)](#11.3.2.1)
the result of writing e via *underlying_* and

    +
          [(11.3.2.2)](#11.3.2.2)
*separator_*, unless e is the last element of r, and

  * [(11.3.3)](#11.3.3)

*closing-bracket_*[.](#11.3.sentence-1)

[12](#12)

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

*Returns*: An iterator past the end of the output range[.](#12.sentence-1)
