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