We convert all contiguous ranges into span of the possibly-const qualified
_Tp (__format::__maybe_const<_Tp, _CharT>). The span object is const qualifed,
to trigger _M_format<const span<T>> specialization, that is already used by
formatter specialization for ranges.
This conversion is applied regardless if range is sized, and ranges::distance
to compute the size. Even for user-defined iterators, they will observe range
being iterated only once.
Finally, using raw pointers to iterate range during formatting guarantees,
that no stdio lock will be taken. In consequence it would be now possible
to enable_nonlocking_formatter_optimization for all contiguous ranges.
libstdc++-v3/ChangeLog:
* include/std/format (range_formatter::format): Format all
contiguous ranges as span<__format::__maybe_const<_Tp, _CharT>>.
---
For the file that formatted vector, array/span (of various sizes), and
views adapated via them I have seen around 1s reduction. Less that I
expected, but I think symbol reduction is valuable. And especially the
fact that such approach could make vector use non-buffered print.
I think we may want to change default enable_nonlocking_formatter_optimization
to be true for contiguous ranges (we may need to check if there is no
user-defined specialization formatter - check if one of our nested
typedefs exits).
I think that is technically non-coforming, but it is safe, and I doubt
people will complain that print with vector is faster. Especially that
for ranges we may need to allocate pretty large string.
Testing on x86_64-linux. *format* test passed in all standard modes.
OK for trunk when all test passes.
libstdc++-v3/include/std/format | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 4627381fa9e..60adca93b5d 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -6175,7 +6175,13 @@ namespace __format
format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
{
using _Range = remove_reference_t<_Rg>;
- if constexpr (__format::__simply_formattable_range<_Range, _CharT>)
+ if constexpr (ranges::contiguous_range<_Rg>)
+ {
+ const span<__format::__maybe_const<_Tp, _CharT>>
+ __spn(ranges::data(__rg), size_t(ranges::distance(__rg)));
+ return _M_format(__spn, __fc);
+ }
+ else if constexpr (__format::__simply_formattable_range<_Range,
_CharT>)
return _M_format<const _Range>(__rg, __fc);
else
return _M_format(__rg, __fc);
--
2.54.0