28 Text processing library [text]
28.5 Formatting [format]
28.5.7 Formatting of ranges [format.range]
28.5.7.1 Variable template format_kind [format.range.fmtkind]
28.5.7.2 Class template range_formatter [format.range.formatter]
28.5.7.3 Class template range-default-formatter [format.range.fmtdef]
28.5.7.4 Specialization of range-default-formatter for maps [format.range.fmtmap]
28.5.7.5 Specialization of range-default-formatter for sets [format.range.fmtset]
28.5.7.6 Specialization of range-default-formatter for strings [format.range.fmtstr]
28.5.7.1 Variable template format_kind [format.range.fmtkind]
template<ranges::input_range R>
requires same_as<R, remove_cvref_t<R>>
constexpr range_format format_kind<R> = see below;
A program that instantiates the primary template of format_kind is ill-formed.
For a type R, format_kind<R> is defined as follows:
Otherwise, if the qualified-id R::key_type is valid and denotes a type:
If the qualified-id R::mapped_type is valid and denotes a type, let U be remove_cvref_t<ranges::range_reference_t<R>>.
If either U is a specialization of pair or U is a specialization of tuple and tuple_size_v<U> == 2, format_kind<R> is range_format::map.
Otherwise, format_kind<R> is range_format::set.
Otherwise, format_kind<R> is range_format::sequence.
Remarks: Pursuant to [namespace.std], users may specialize format_kind for cv-unqualified program-defined types that model ranges::input_range.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const range_format.
28.5.7.2 Class template range_formatter [format.range.formatter]
namespace std { template<class T, class charT = char> requires same_as<remove_cvref_t<T>, T> && formattable<T, charT> class range_formatter { formatter<T, charT> underlying_; basic_string_view<charT> separator_ = STATICALLY-WIDEN<charT>(", "); basic_string_view<charT> opening-bracket_ = STATICALLY-WIDEN<charT>("["); basic_string_view<charT> closing-bracket_ = STATICALLY-WIDEN<charT>("]"); 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 R, class FormatContext> requires formattable<ranges::range_reference_t<R>, charT> && same_as<remove_cvref_t<ranges::range_reference_t<R>>, T> constexpr typename FormatContext::iterator format(R&& r, FormatContext& ctx) const; }; }
The class template range_formatter is a utility for implementing formatter specializations for range types.
range_formatter interprets format-spec as a range-format-spec.
The syntax of format specifications is as follows:
range-format-spec :
range-fill-and-align width n range-type range-underlying-spec
range-fill-and-align :
range-fill align
range-fill :
any character other than { or } or :
range-underlying-spec :
: format-spec
For range_formatter<T, charT>, the format-spec in a range-underlying-spec, if any, is interpreted by formatter<T, charT>.
The n option causes the range to be formatted without the opening and closing brackets.
The range-type specifier changes the way a range is formatted, with certain options only valid with certain argument types.
The meaning of the various type options is as specified in Table 115.
Table 115 — Meaning of range-type options [tab:formatter.range.type]
Option | Requirements | Meaning |
m | T shall be either a specialization of pair or a specialization of tuple such that tuple_size_v<T> is 2. | 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. |
s | T shall be charT. | Indicates that the range should be formatted as a string. |
?s | T shall be charT. | Indicates that the range should be formatted as an escaped string ([format.string.escaped]). |
If the range-type is s or ?s, then there shall be no n option and no range-underlying-spec.
constexpr void set_separator(basic_string_view<charT> sep) noexcept;
Effects: Equivalent to: separator_ = sep;
constexpr void set_brackets(basic_string_view<charT> opening,
basic_string_view<charT> closing) noexcept;
Effects: Equivalent to: opening-bracket_ = opening; closing-bracket_ = closing;
template<class ParseContext>
constexpr typename ParseContext::iterator
parse(ParseContext& ctx);
Effects: Parses the format specifiers as a range-format-spec and stores the parsed specifiers in *this.
Calls underlying_.parse(ctx) to parse format-spec in range-format-spec or, if the latter is not present, an empty format-spec.
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.
If:
- the range-type is neither s nor ?s,
- underlying_.set_debug_format() is a valid expression, and
- there is no range-underlying-spec,
then calls underlying_.set_debug_format().
Returns: An iterator past the end of the range-format-spec.
template<ranges::input_range R, class FormatContext>
requires formattable<ranges::range_reference_t<R>, charT> &&
same_as<remove_cvref_t<ranges::range_reference_t<R>>, T>
typename FormatContext::iterator
format(R&& r, FormatContext& ctx) const;
Effects: Writes the following into ctx.out(), adjusted according to the range-format-spec:
If the range-type was s, then as if by formatting basic_string<charT>(from_range, r).
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]).
Otherwise,
- opening-bracket_,
- for each element e of the range r:
- the result of writing e via underlying_ and
- separator_, unless e is the last element of r, and
- closing-bracket_.
Returns: An iterator past the end of the output range.
28.5.7.3 Class template range-default-formatter [format.range.fmtdef]
namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::sequence, R, charT> { private: using maybe-const-r = fmt-maybe-const<R, charT>; range_formatter<remove_cvref_t<ranges::range_reference_t<maybe-const-r>>, charT> underlying_; 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; template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> constexpr typename FormatContext::iterator format(maybe-const-r& elems, FormatContext& ctx) const; }; }
constexpr void set_separator(basic_string_view<charT> sep) noexcept;
Effects: Equivalent to: underlying_.set_separator(sep);
constexpr void set_brackets(basic_string_view<charT> opening,
basic_string_view<charT> closing) noexcept;
Effects: Equivalent to: underlying_.set_brackets(opening, closing);
template<class ParseContext>
constexpr typename ParseContext::iterator
parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext>
typename FormatContext::iterator
format(maybe-const-r& elems, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(elems, ctx);
28.5.7.4 Specialization of range-default-formatter for maps [format.range.fmtmap]
namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::map, R, charT> { private: using maybe-const-map = fmt-maybe-const<R, charT>; using element-type = remove_cvref_t<ranges::range_reference_t<maybe-const-map>>; range_formatter<element-type, charT> underlying_; public: constexpr range-default-formatter(); template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> constexpr typename FormatContext::iterator format(maybe-const-map& r, FormatContext& ctx) const; }; }
constexpr range-default-formatter();
Mandates: Either:
- element-type is a specialization of pair, or
- element-type is a specialization of tuple and tuple_size_v<element-type> == 2.
Effects: Equivalent to: underlying_.set_brackets(STATICALLY-WIDEN<charT>("{"), STATICALLY-WIDEN<charT>("}")); underlying_.underlying().set_brackets({}, {}); underlying_.underlying().set_separator(STATICALLY-WIDEN<charT>(": "));
template<class ParseContext>
constexpr typename ParseContext::iterator
parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext>
typename FormatContext::iterator
format(maybe-const-map& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r, ctx);
28.5.7.5 Specialization of range-default-formatter for sets [format.range.fmtset]
namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::set, R, charT> { private: using maybe-const-set = fmt-maybe-const<R, charT>; range_formatter<remove_cvref_t<ranges::range_reference_t<maybe-const-set>>, charT> underlying_; public: constexpr range-default-formatter(); template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> constexpr typename FormatContext::iterator format(maybe-const-set& r, FormatContext& ctx) const; }; }
constexpr range-default-formatter();
Effects: Equivalent to: underlying_.set_brackets(STATICALLY-WIDEN<charT>("{"), STATICALLY-WIDEN<charT>("}"));
template<class ParseContext>
constexpr typename ParseContext::iterator
parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext>
typename FormatContext::iterator
format(maybe-const-set& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r, ctx);
28.5.7.6 Specialization of range-default-formatter for strings [format.range.fmtstr]
namespace std { template<range_format K, ranges::input_range R, class charT> requires (K == range_format::string || K == range_format::debug_string) struct range-default-formatter<K, R, charT> { private: formatter<basic_string<charT>, charT> underlying_; public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> constexpr typename FormatContext::iterator format(see below& str, FormatContext& ctx) const; }; }
template<class ParseContext>
constexpr typename ParseContext::iterator
parse(ParseContext& ctx);
Effects: Equivalent to: auto i = underlying_.parse(ctx); if constexpr (K == range_format::debug_string) { underlying_.set_debug_format(); } return i;
template<class FormatContext>
typename FormatContext::iterator
format(see below& r, FormatContext& ctx) const;
The type of r is const R& if ranges::input_range<const R> is true and R& otherwise.
Effects: Let s be a basic_string<charT> such that ranges::equal(s, r) is true.
Equivalent to: return underlying_.format(s, ctx);