std::advance istreambuf_iterator overload

Jonathan Wakely jwakely@redhat.com
Fri Nov 10 20:57:00 GMT 2017


On 09/11/17 22:12 +0100, François Dumont wrote:
>Hi
>
>    Working on istreambuf_iterator I realized that this iterator would 
>really benefit from an std::advance overload so here it is.


>    Tested under Linux x86_64 normal and debug modes, ok to commit ?
>
>François
>

>diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
>index 0a6c7f9..b60626a 100644
>--- a/libstdc++-v3/include/bits/streambuf_iterator.h
>+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
>@@ -417,6 +421,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       return __last;
>     }
> 
>+  template<typename _CharT, typename _Distance>
>+    inline _GLIBCXX17_CONSTEXPR void

This function can never be constexpr.

>+    advance(istreambuf_iterator<_CharT>& __i, _Distance __n)
>+    {
>+      if (__n == 0)
>+	return;
>+
>+      __glibcxx_assert(__n > 0);
>+      __glibcxx_requires_cond(!__i._M_at_eof(),
>+			      _M_message(__gnu_debug::__msg_inc_istreambuf)
>+			      ._M_iterator(__i));
>+
>+      typedef istreambuf_iterator<_CharT>		   __is_iterator_type;
>+      typedef typename __is_iterator_type::traits_type	   traits_type;
>+      typedef typename __is_iterator_type::streambuf_type  streambuf_type;
>+      typedef typename traits_type::int_type		   int_type;
>+      const int_type __eof = traits_type::eof();
>+
>+      streambuf_type* __sb = __i._M_sbuf;

This function relies on private members of istreambuf_iterator which
may not be present in a user-defined specialization of
istreambuf_iterator.

I think realistically you can only do this optimization for
istreambuf_iterator<char> and istreambuf_iterator<wchar_t>. Look at
how the std::copy and std::find overloads are contrained with
__is_char.

>+      int_type __c = __sb->sgetc();
>+      while (__n && !traits_type::eq_int_type(__c, __eof))

Can we use __n > 0 as the condition? Would it give better behaviour
for negative values in non-debug mode?

>+	{
>+	  streamsize __size = __sb->egptr() - __sb->gptr();
>+	  if (__size > __n)
>+	    {
>+	      __sb->__safe_gbump(__n);
>+	      __n = 0;
>+	    }
>+	  else if (__size > 1)
>+	    {
>+	      __sb->__safe_gbump(__size);
>+	      __n -= __size;
>+	      __c = __sb->underflow();
>+	    }
>+	  else
>+	    {
>+	      --__n;
>+	      __c = __sb->snextc();
>+	    }

It seems like it should be possible to optimize this loop, but I don't
see an obvious way to improve it.

>+	}
>+
>+      __glibcxx_requires_cond(__n == 0,
>+			      _M_message(__gnu_debug::__msg_inc_istreambuf)
>+			      ._M_iterator(__i));
>+      __i._M_c = __eof;
>+      if (traits_type::eq_int_type(__c, __eof))
>+	__i._M_sbuf = 0;
>+    }
>+


>diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc b/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc
>new file mode 100644
>index 0000000..7c3f882
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc

Thanks for the comprehensive tests, they look great.




More information about the Libstdc++ mailing list