std::advance istreambuf_iterator overload

François Dumont frs.dumont@gmail.com
Mon Nov 13 20:23:00 GMT 2017


On 10/11/2017 21:57, Jonathan Wakely wrote:
> 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.

I just replicate the _GLIBCXX17_CONSTEXPR qualification of the general 
std::advance overload. I am not clear about those different constexpr 
concepts but I also found strange that it could be consider as such.

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

I wondered why copy or find were constrained this way, thanks for 
explaining. I have done the same for std::advance.

>
>> +      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?
Indeed, it is better with this check.
>
>> +    {
>> +      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.
It sounds like a Fermat quotes :-)

But I thought twice about this implementation and here is a new proposal.

François

-------------- next part --------------
A non-text attachment was scrubbed...
Name: advance_istreambuf_iter.patch
Type: text/x-patch
Size: 21147 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20171113/8ebbd48e/attachment.bin>


More information about the Libstdc++ mailing list