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>>.
---
 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

Reply via email to