https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109400

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #0)
> Additionally, std::ranges::advance is not specialized for
> std::istreambuf_iterator so just increments character by character. The
> ranges::advance(i, n) form should use std::advance. The ranges::advance(i,
> sentinel) form will already be optimal when the sentinel is the same type as
> the iterator, but will be slow when using default_sentinel_t.

Oops, assignable_from<istreambuf_iterator<char>&, default_sentinel_t> is
satisfied, via the non-explicit istreambuf_iterator(default_sentinel_t)
constructor, so it already works efficiently with default_sentinel.

> The
> ranges::advance(i, n, sentinel) form could be done efficiently, and has the
> advantage that it's not undefined if EOF is reached before advancing n times.

This could still be improved though.

Something like this:

--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -42,6 +42,17 @@
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+template<typename> class char_traits;
+template<typename, typename> class istreambuf_iterator;
+template<typename _Tp>
+  static constexpr bool __is_istreambuf_iter = false;
+
+template<typename _CharT>
+  static constexpr bool
+  __is_istreambuf_iter<istreambuf_iterator<_CharT, char_traits<_CharT>>>
+    = std::__is_char<_CharT>::__value;
+
 namespace ranges
 {
   template<typename>
@@ -737,6 +748,8 @@ namespace ranges
                while (++__n);
              }
          }
+       else if constexpr (__is_istreambuf_iter<_It>)
+         std::advance(__it, __n);
        else
          {
            // cannot decrement a non-bidirectional iterator
@@ -791,6 +804,11 @@ namespace ranges
          return __n;
        else if (__n > 0)
          {
+           if constexpr (__is_istreambuf_iter<_It>)
+             {
+               // TODO need access to __it._M_sbuf
+             }
+
            iter_difference_t<_It> __m = 0;
            do
              {

But it seems to me that it would be helpful if ranges::advance was a
customization point, so that program-defined iterators could provide an
optimized implementation too.

Reply via email to