]> git.ipfire.org Git - thirdparty/gcc.git/commit
libstdc++: Implement formatter for ranges and range_formatter [PR109162]
authorTomasz Kamiński <tkaminsk@redhat.com>
Fri, 28 Mar 2025 08:30:22 +0000 (09:30 +0100)
committerTomasz Kamiński <tkaminsk@redhat.com>
Tue, 15 Apr 2025 15:09:59 +0000 (17:09 +0200)
commitf62e5d720de829cf346b799f3463fee53728ba6c
tree04752db00b2cc3c9aa1f60ba1fe9dcc7fa4e6213
parenta039bab95750ead133e48672ab33378f513ba287
libstdc++: Implement formatter for ranges and range_formatter [PR109162]

This patch implements formatter specialization for input_ranges and
range_formatter class from P2286R8, as adjusted by P2585R1. The formatter
for pair/tuple is not yet provided, making maps not formattable.

This introduces an new _M_format_range member to internal __formatter_str,
that formats range as _CharT as string, according to the format spec.
This function transform any contiguous range into basic_string_view directly,
by computing size if necessary. Otherwise, for ranges for which size can be
computed (forward_range or sized_range) we use a stack buffer, if they are
sufficiently small. Finally, we create a basic_string<_CharT> from the range,
and format its content.

In case when padding is specified, this is handled by firstly formatting
the content of the range to the temporary string object. However, this can be
only implemented if the iterator of the basic_format_context is internal
type-erased iterator used by implementation. Otherwise a new basic_format_context
would need to be created, which would require rebinding of handles stored in
the arguments: note that format spec for element type could retrieve any format
argument from format context, visit and use handle to format it.
As basic_format_context provide no user-facing constructor, the user are not able
to construct object of that type with arbitrary iterators.

The signatures of the user-facing parse and format methods of the provided
formatters deviate from the standard by constraining types of params:
* _CharT is constrained __formatter::__char
* basic_format_parse_context<_CharT> for parse argument
* basic_format_context<_Out, _CharT> for format second argument
The standard specifies last three of above as unconstrained types. These types
are later passed to possibly user-provided formatter specializations, that are
required via formattable concept to only accept above types.

Finally, the formatter<input_range, _CharT> specialization is implemented
without using specialization of range-default-formatter exposition only
template as base class, while providing same functionality.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/std/format (__format::__has_debug_format, _Pres_type::_Pres_seq)
(_Pres_type::_Pres_str, __format::__Stackbuf_size): Define.
(_Separators::_S_squares, _Separators::_S_parens, _Separators::_S_comma)
(_Separators::_S_colon): Define additional constants.
(_Spec::_M_parse_fill_and_align): Define overload accepting
list of excluded characters for fill, and forward existing overload.
(__formatter_str::_M_format_range): Define.
(__format::_Buf_sink) Use __Stackbuf_size for size of array.
(__format::__is_map_formattable, std::range_formatter)
(std::formatter<_Rg, _CharT>): Define.
* src/c++23/std.cc.in (std::format_kind, std::range_format)
(std::range_formatter): Export.
* testsuite/std/format/formatter/lwg3944.cc: Guarded tests with
__glibcxx_format_ranges.
* testsuite/std/format/formatter/requirements.cc: Adjusted for standard
behavior.
* testsuite/23_containers/vector/bool/format.cc: Test vector<bool> formatting.
* testsuite/std/format/ranges/format_kind.cc: New test.
* testsuite/std/format/ranges/formatter.cc: New test.
* testsuite/std/format/ranges/sequence.cc: New test.
* testsuite/std/format/ranges/string.cc: New test.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
libstdc++-v3/include/std/format
libstdc++-v3/src/c++23/std.cc.in
libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
libstdc++-v3/testsuite/std/format/formatter/requirements.cc
libstdc++-v3/testsuite/std/format/ranges/format_kind.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/format/ranges/formatter.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/format/ranges/sequence.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/format/ranges/string.cc [new file with mode: 0644]