diff --git a/source/containers.tex b/source/containers.tex index dae29df486..e54959650a 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -13035,159 +13035,6 @@ \end{codeblock} \end{itemdescr} -\rSec1[assoc.format]{Associative formatting} - -\pnum -For each of -\tcode{map}, -\tcode{multimap}, -\tcode{unordered_map}, -\tcode{unordered_multimap}, -\tcode{flat_map}, and -\tcode{flat_multimap}, -the library provides the following formatter specialization -where \tcode{\placeholder{map-type}} is the name of the template: - -\indexlibraryglobal{formatter}% -\begin{codeblock} -namespace std { - template T, class... U> - requires @\libconcept{formattable}@ - struct formatter<@\placeholder{map-type}@, charT> { - private: - using @\exposid{maybe-const-map}@ = // \expos - @\exposid{fmt-maybe-const}@<@\placeholder{map-type}@, charT>; - range_formatter>, - charT> @\exposid{underlying_}@; // \expos - public: - constexpr formatter(); - - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - typename FormatContext::iterator - format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; - }; -} -\end{codeblock} - -\indexlibraryctor{formatter}% -\begin{itemdecl} -constexpr formatter(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); -@\exposid{underlying_}@.underlying().set_brackets({}, {}); -@\exposid{underlying_}@.underlying().set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{parse}{formatter}% -\begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} -\end{itemdescr} - -\indexlibrarymember{format}{formatter}% -\begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} -\end{itemdescr} - -\pnum -For each of -\tcode{set}, -\tcode{multiset}, -\tcode{unordered_set}, -\tcode{unordered_multiset}, -\tcode{flat_set}, and -\tcode{flat_multiset}, -the library provides the following formatter specialization -where \tcode{\placeholder{set-type}} is the name of the template: - -\indexlibraryglobal{formatter}% -\begin{codeblock} -namespace std { -template - requires @\libconcept{formattable}@ - struct formatter<@\placeholder{set-type}@, charT> { - private: - range_formatter @\exposid{underlying_}@; // \expos - public: - constexpr formatter(); - - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - typename FormatContext::iterator - format(const @\placeholder{set-type}@& r, FormatContext& ctx) const; - }; -} -\end{codeblock} - -\indexlibraryctor{formatter}% -\begin{itemdecl} -constexpr formatter(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{parse}{formatter}% -\begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} -\end{itemdescr} - -\indexlibrarymember{format}{formatter}% -\begin{itemdecl} -template - typename FormatContext::iterator - format(const @\placeholder{set-type}@& r, FormatContext& ctx) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} -\end{itemdescr} - \rSec1[container.adaptors]{Container adaptors} \rSec2[container.adaptors.general]{In general} diff --git a/source/utilities.tex b/source/utilities.tex index 4c5f857525..240255ab61 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -13859,22 +13859,6 @@ // \ref{format.formatter}, formatter template struct formatter; - // \ref{format.formatter.spec}, formatter specializations - template - requires (!@\libconcept{same_as}@>, R>) && - @\libconcept{formattable}@, charT> - struct formatter; - - // \ref{format.range.formatter}, class template \tcode{range_formatter} - template - requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ - class range_formatter; - - // \ref{format.parse.ctx}, class template \tcode{basic_format_parse_context} - template class basic_format_parse_context; - using format_parse_context = basic_format_parse_context; - using wformat_parse_context = basic_format_parse_context; - // \ref{format.formattable}, concept \libconcept{formattable} template concept formattable = @\seebelow@; @@ -13888,6 +13872,44 @@ using @\exposid{fmt-maybe-const}@ = // \expos conditional_t<@\exposconcept{const-formattable-range}@, const R, R>; + // \ref{format.parse.ctx}, class template \tcode{basic_format_parse_context} + template class basic_format_parse_context; + using format_parse_context = basic_format_parse_context; + using wformat_parse_context = basic_format_parse_context; + + // \ref{format.range}, formatting of ranges + // \ref{format.range.fmtkind}, variable template \tcode{format_kind} + enum class range_format { + disabled, + map, + set, + sequence, + string, + debug_string + }; + + template + constexpr @\unspec@ format_kind = @\unspec@; + + template + requires @\libconcept{same_as}@> + constexpr range_format format_kind = @\seebelow@; + + // \ref{format.range.formatter}, class template \tcode{range_formatter} + template + requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ + class range_formatter; + + // \ref{format.range.fmtdef}, class template \tcode{\exposid{range-default-formatter}} + template + struct @\exposid{range-default-formatter}@; // \expos + + // \ref{format.range.fmtmap}, \ref{format.range.fmtset}, \ref{format.range.fmtstr}, specializations for maps, sets, and strings + template + requires (format_kind != range_format::disabled) && + @\libconcept{formattable}@, charT> + struct formatter : @\exposid{range-default-formatter}@, R, charT> { }; + // \ref{format.arguments}, arguments // \ref{format.arg}, class template \tcode{basic_format_arg} template class basic_format_arg; @@ -15649,7 +15671,97 @@ \end{codeblock} \end{example} -\rSec2[format.range.formatter]{Class template \tcode{range_formatter}} +\rSec2[format.range]{Formatting of ranges} + +\rSec3[format.range.fmtkind]{Variable template \tcode{format_kind}} + +\indexlibraryglobal{format_kind} +\begin{itemdecl} +template + requires @\libconcept{same_as}@> + constexpr range_format format_kind = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +A program that instantiates the primary template of \tcode{format_kind} +is ill-formed. + +\pnum +For a type \tcode{R}, \tcode{format_kind} is defined as follows: +\begin{itemize} +\item +If \tcode{\libconcept{same_as}>, R>} +is \tcode{true}, +\tcode{format_kind} is \tcode{range_format::disabled}. +\begin{note} +This prevents constraint recursion for ranges whose +reference type is the same range type. +For example, +\tcode{std::filesystem::path} is a range of \tcode{std::filesystem::path}. +\end{note} + +\item +Otherwise, if the \grammarterm{qualified-id} \tcode{R::key_type} +is valid and denotes a type: +\begin{itemize} +\item +If the \grammarterm{qualified-id} \tcode{R::mapped_type} +is valid and denotes a type, +let \tcode{U} be \tcode{remove_cvref_t>}. +If either \tcode{U} is a specialization of \tcode{pair} or +\tcode{U} is a specialization of \tcode{tuple} and +\tcode{tuple_size_v == 2}, +\tcode{format_kind} is \tcode{range_format::map}. +\item +Otherwise, \tcode{format_kind} is \tcode{range_format::set}. +\end{itemize} + +\item +Otherwise, \tcode{format_kind} is \tcode{range_format::sequence}. +\end{itemize} + +\pnum +\remarks +Pursuant to \ref{namespace.std}, users may specialize \tcode{format_kind} +for cv-unqualified program-defined types +that model \tcode{ranges::\libconcept{input_range}}. +Such specializations shall be usable in constant expressions\iref{expr.const} +and have type \tcode{const range_format}. +\end{itemdescr} + +\rSec3[format.range.formatter]{Class template \tcode{range_formatter}} + +\indexlibraryglobal{range_formatter}% +\begin{codeblock} +namespace std { + template + requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ + class range_formatter { + formatter @\exposid{underlying_}@; // \expos + basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos + basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("["); // \expos + basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("]"); // \expos + + public: + constexpr void set_separator(basic_string_view sep); + constexpr void set_brackets(basic_string_view opening, + basic_string_view closing); + constexpr formatter& underlying() { return @\exposid{underlying_}@; } + constexpr const formatter& underlying() const { return @\exposid{underlying_}@; } + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + requires @\libconcept{formattable}@, charT> && + @\libconcept{same_as}@>, T> + typename FormatContext::iterator + format(R&& r, FormatContext& ctx) const; + }; +} +\end{codeblock} \pnum The class template \tcode{range_formatter} is a utility @@ -15749,37 +15861,6 @@ then there shall be no \tcode{n} option and no \fmtgrammarterm{range-underlying-spec}. -\indexlibraryglobal{range_formatter}% -\begin{codeblock} -namespace std { - template - requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ - class range_formatter { - formatter @\exposid{underlying_}@; // \expos - basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos - basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("["); // \expos - basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("]"); // \expos - - public: - constexpr void set_separator(basic_string_view sep); - constexpr void set_brackets(basic_string_view opening, - basic_string_view closing); - constexpr formatter& underlying() { return @\exposid{underlying_}@; } - constexpr const formatter& underlying() const { return @\exposid{underlying_}@; } - - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - requires @\libconcept{formattable}@, charT> && - @\libconcept{same_as}@>, T> - typename FormatContext::iterator - format(R&& r, FormatContext& ctx) const; - }; -} -\end{codeblock} - \indexlibrarymember{set_separator}{range_formatter}% \begin{itemdecl} constexpr void set_separator(basic_string_view sep); @@ -15884,13 +15965,13 @@ An iterator past the end of the output range. \end{itemdescr} -\indexlibraryglobal{formatter}% +\rSec3[format.range.fmtdef]{Class template \tcode{\exposid{range-default-formatter}}} + +\indexlibraryglobal{\exposid{range-default-formatter}}% \begin{codeblock} namespace std { template - requires (!@\libconcept{same_as}@>, R>) && - @\libconcept{formattable}@, charT> - struct formatter { + struct @\exposid{range-default-formatter}@ { private: using @\exposid{maybe-const-r}@ = @\exposid{fmt-maybe-const}@; range_formatter>, @@ -15912,16 +15993,7 @@ } \end{codeblock} -\pnum -\begin{note} -The \tcode{(!\libconcept{same_as}>, R>)} -constraint prevents constraint recursion -for ranges whose reference type is the same range type. -For example, \tcode{std::filesystem::path} -is a range of \tcode{std::filesystem::path}. -\end{note} - -\indexlibrarymember{set_separator}{formatter}% +\indexlibrarymember{set_separator}{\exposid{range-default-formatter}}% \begin{itemdecl} constexpr void set_separator(basic_string_view sep); \end{itemdecl} @@ -15932,7 +16004,7 @@ Equivalent to: \tcode{\exposid{underlying_}.set_separator(sep);} \end{itemdescr} -\indexlibrarymember{set_brackets}{formatter}% +\indexlibrarymember{set_brackets}{\exposid{range-default-formatter}}% \begin{itemdecl} constexpr void set_brackets(basic_string_view opening, basic_string_view closing); \end{itemdecl} @@ -15943,7 +16015,7 @@ Equivalent to: \tcode{\exposid{underlying_}.set_brackets(opening, closing);} \end{itemdescr} -\indexlibrarymember{parse}{formatter}% +\indexlibrarymember{parse}{\exposid{range-default-formatter}}% \begin{itemdecl} template constexpr typename ParseContext::iterator @@ -15956,7 +16028,7 @@ Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} \end{itemdescr} -\indexlibrarymember{format}{formatter}% +\indexlibrarymember{format}{\exposid{range-default-formatter}}% \begin{itemdecl} template typename FormatContext::iterator @@ -15969,6 +16041,219 @@ Equivalent to: \tcode{return \exposid{underlying_}.format(elems, ctx);} \end{itemdescr} +\rSec3[format.range.fmtmap]{Specialization of \tcode{\exposid{range-default-formatter}} for maps} + +\indexlibraryglobal{\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + struct @\exposid{range-default-formatter}@ { + private: + using @\exposid{maybe-const-map}@ = @\exposid{fmt-maybe-const}@; // \expos + using @\exposid{element-type}@ = // \expos + remove_cvref_t>; + range_formatter<@\exposid{element-type}@, charT> @\exposid{underlying_}@; // \expos + public: + constexpr @\exposid{range-default-formatter}@(); + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibraryctor{\exposid{range-default-formatter}}% +\begin{itemdecl} +constexpr @\exposid{range-default-formatter}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Either: +\begin{itemize} +\item +\exposid{element-type} is a specialization of \tcode{pair}, or +\item +\exposid{element-type} is a specialization of \tcode{tuple} and +\tcode{tuple_size_v == 2}. +\end{itemize} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); +@\exposid{underlying_}@.underlying().set_brackets({}, {}); +@\exposid{underlying_}@.underlying().set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{parse}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymember{format}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} +\end{itemdescr} + +\rSec3[format.range.fmtset]{Specialization of \tcode{\exposid{range-default-formatter}} for sets} + +\indexlibraryglobal{\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + struct @\exposid{range-default-formatter}@ { + private: + using @\exposid{maybe-const-set}@ = @\exposid{fmt-maybe-const}@; // \expos + range_formatter>, + charT> @\exposid{underlying_}@; // \expos + + public: + constexpr @\exposid{range-default-formatter}@(); + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibraryctor{\exposid{range-default-formatter}}% +\begin{itemdecl} +constexpr @\exposid{range-default-formatter}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{parse}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymember{format}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} +\end{itemdescr} + +\rSec3[format.range.fmtstr]{Specialization of \tcode{\exposid{range-default-formatter}} for strings} + +\indexlibraryglobal{\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + requires (K == range_format::string || K == range_format::debug_string) + struct @\exposid{range-default-formatter}@ { + private: + formatter, charT> @\exposid{underlying_}@; // \expos + + public: + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\seebelow@& str, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\pnum +\mandates +\tcode{\libconcept{same_as}>, charT>} +is \tcode{true}. + +\indexlibrarymember{parse}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto i = @\exposid{underlying_}@.parse(ctx); +if constexpr (K == range_format::debug_string) { + @\exposid{underlying_}@.set_debug_format(); +} +return i; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{format}{\exposid{range-default-formatter}}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\seebelow@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type of \tcode{r} is \tcode{const R\&} +if \tcode{\libconcept{input_range}} is \tcode{true} and +\tcode{R\&} otherwise. + +\pnum +\effects +Let \tcode{\placeholder{s}} be a \tcode{basic_string} such that +\tcode{ranges::equal(\placeholder{s}, r)} is \tcode{true}. +Equivalent to: \tcode{return \exposid{underlying_}.format(\placeholder{s}, ctx);} +\end{itemdescr} + \rSec2[format.arguments]{Arguments} \rSec3[format.arg]{Class template \tcode{basic_format_arg}}