id summary reporter owner description type status milestone component version severity resolution keywords cc 10847 Offset overloads of next() / prior() have stopped compiling for iterators that previously worked Tony Lewis No-Maintainer "=== 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 #include #include #include int main() { boost::ptr_set 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 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; _Sequence = std::__debug::list; __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::call(T, Distance) [with T = __gnu_debug::_Safe_iterator, std::__debug::list >; Distance = int]’ /usr/include/boost/next_prior.hpp:151:67: required from ‘T boost::next(T, Distance) [with T = __gnu_debug::_Safe_iterator, std::__debug::list >; 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’ 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; _Sequence = std::__debug::set, int, int>, std::allocator >; __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& boost::void_ptr_iterator::operator+=(boost::void_ptr_iterator::difference_type) [with VoidIter = __gnu_debug::_Safe_iterator, std::__debug::set, int, int>, std::allocator > >; T = int; boost::void_ptr_iterator::difference_type = int]’ /usr/include/boost/next_prior.hpp:73:11: required from ‘static T boost::next_prior_detail::next_impl1::call(T, Distance) [with T = boost::void_ptr_iterator<__gnu_debug::_Safe_iterator, std::__debug::set, int, int>, std::allocator > >, 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::__debug::set, int, int>, std::allocator > >, 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’ 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)" Bugs closed Boost 1.58.0 utility Boost 1.57.0 Regression fixed next,prior,advance,iterator,category,type_traits,has_plus_assign,forward_iterator raad@… Andrey.Semashev@…