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.