[Boost-bugs] [Boost C++ Libraries] #10847: Offset overloads of next() / prior() have stopped compiling for iterators that previously worked

Subject: [Boost-bugs] [Boost C++ Libraries] #10847: Offset overloads of next() / prior() have stopped compiling for iterators that previously worked
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-12-04 16:20:08


#10847: Offset overloads of next() / prior() have stopped compiling for iterators
that previously worked
-------------------------------------------------+-------------------------
 Reporter: Tony Lewis <tonyelewis@…> | Owner: no-
     Type: Bugs | maintainer
Milestone: Boost 1.58.0 | Status: new
  Version: Boost 1.57.0 | Component: utility
 Keywords: | Severity: Regression
  next,prior,advance,iterator,category,type_traits,has_plus_assign,forward_iterator|
-------------------------------------------------+-------------------------
 === Summary ===

 In Boost v1.57.0, the offset overloads of `boost::next()` /
 `boost::prior()` have stopped compiling for iterators that previously
 worked in <= v1.56.0.

 I think this is because commit 651a869d4f9479dd3dfdd0293305a60b8c8d0e1c
 (Boost Trac won't let me paste link without passing some non-existent
 captcha) has replaced a call to `std::advance()` with a custom approach
 using type_traits (such as `has_plus_assign`).

 Unfortunately some iterators indicate their non-provision of random-access
 through their iterator category (eg `forward_iterator_tag`) but provide
 `operator+=` and `operator+` methods/functions that don't compile.

 Examples:
  * iterators returned by boost::ptr_set and
  * iterators returned by GCC's std::list<> when `_GLIBCXX_DEBUG` is
 defined

 Importantly, these iterators work without problem under:
  * std::advance(),
  * Boost v1.56.0's `boost::next()` / `boost::prior()` and
  * C++11's `std::next()` / `std::prev()` (at least under GCC v4.9.1's
 implementation)

 ...so Boost v1.57.0 `next()` / `prior()` are out of step with the standard
 (or `std::`) approach.

 === Example ===

 Attempting to compile:

 {{{
 #include <boost/next_prior.hpp>
 #include <boost/ptr_container/ptr_set.hpp>

 #include <iostream>
 #include <list>

 int main() {
         boost::ptr_set<int> the_ptr_set;
         the_ptr_set.insert( new int( 1 ) );
         the_ptr_set.insert( new int( 2 ) );
         std::cerr << *boost::next( the_ptr_set.begin(), 1 ) << std::endl;

         std::list<int> the_list;
         the_list.push_back( 1 );
         the_list.push_back( 2 );
         std::cerr << *boost::next( the_list.begin(), 1 ) << std::endl;

         return 0;
 }
 }}}

 ...with `g++ -D_GLIBCXX_DEBUG -o next_prior_prob next_prior_prob.cpp` (GCC
 v4.9.1) produces the following compiler errors:

 {{{
 In file included from /usr/include/c++/4.9/debug/set.h:33:0,
                  from /usr/include/c++/4.9/debug/set:33,
                  from /usr/include/c++/4.9/set:66,
                  from /usr/include/boost/ptr_container/ptr_set.hpp:21,
                  from next_prior_prob.cpp:2:
 /usr/include/c++/4.9/debug/safe_iterator.h: In instantiation of
 â€˜__gnu_debug::_Safe_iterator<_Iterator, _Sequence>&
 __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::operator+=(const
 difference_type&) [with _Iterator = std::__cxx1998::_List_iterator<int>;
 _Sequence = std::__debug::list<int>;
 __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::difference_type =
 int]’:
 /usr/include/boost/next_prior.hpp:73:11: required from ‘static T
 boost::next_prior_detail::next_impl1<T, Distance, true>::call(T, Distance)
 [with T = __gnu_debug::_Safe_iterator<std::__cxx1998::_List_iterator<int>,
 std::__debug::list<int> >; Distance = int]’
 /usr/include/boost/next_prior.hpp:151:67: required from ‘T
 boost::next(T, Distance) [with T =
 __gnu_debug::_Safe_iterator<std::__cxx1998::_List_iterator<int>,
 std::__debug::list<int> >; Distance = int]’
 next_prior_prob.cpp:16:49: required from here
 /usr/include/c++/4.9/debug/safe_iterator.h:357:13: error: no match for
 â€˜operator+=’ (operand types are ‘std::__cxx1998::_List_iterator<int>’ and
 â€˜const difference_type {aka const int}’)
   _M_current += __n;
              ^
 /usr/include/c++/4.9/debug/safe_iterator.h: In instantiation of
 â€˜__gnu_debug::_Safe_iterator<_Iterator, _Sequence>&
 __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::operator+=(const
 difference_type&) [with _Iterator = std::_Rb_tree_const_iterator<void*>;
 _Sequence = std::__debug::set<void*,
 boost::void_ptr_indirect_fun<std::less<int>, int, int>,
 std::allocator<void*> >; __gnu_debug::_Safe_iterator<_Iterator,
 _Sequence>::difference_type = int]’:
 /usr/include/boost/ptr_container/detail/void_ptr_iterator.hpp:104:23:
 required from ‘boost::void_ptr_iterator<VoidIter, T>&
 boost::void_ptr_iterator<VoidIter,
 T>::operator+=(boost::void_ptr_iterator<VoidIter, T>::difference_type)
 [with VoidIter =
 __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<void*>,
 std::__debug::set<void*, boost::void_ptr_indirect_fun<std::less<int>, int,
 int>, std::allocator<void*> > >; T = int;
 boost::void_ptr_iterator<VoidIter, T>::difference_type = int]’
 /usr/include/boost/next_prior.hpp:73:11: required from ‘static T
 boost::next_prior_detail::next_impl1<T, Distance, true>::call(T, Distance)
 [with T =
 boost::void_ptr_iterator<__gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<void*>,
 std::__debug::set<void*, boost::void_ptr_indirect_fun<std::less<int>, int,
 int>, std::allocator<void*> > >, int>; Distance = int]’
 /usr/include/boost/next_prior.hpp:151:67: required from ‘T
 boost::next(T, Distance) [with T =
 boost::void_ptr_iterator<__gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<void*>,
 std::__debug::set<void*, boost::void_ptr_indirect_fun<std::less<int>, int,
 int>, std::allocator<void*> > >, int>; Distance = int]’
 next_prior_prob.cpp:11:52: required from here
 /usr/include/c++/4.9/debug/safe_iterator.h:357:13: error: no match for
 â€˜operator+=’ (operand types are ‘std::_Rb_tree_const_iterator<void*>’ and
 â€˜const difference_type {aka const int}’)
 }}}

 (but has no problems if `boost::next()` is replaced with `std::next()` and
 `-std=c++11` is used)

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/10847>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:17 UTC