Opened 8 years ago
Closed 5 years ago
#10847 closed Bugs (fixed)
Offset overloads of next() / prior() have stopped compiling for iterators that previously worked
Reported by: | Owned by: | No-Maintainer | |
---|---|---|---|
Milestone: | Boost 1.58.0 | Component: | utility |
Version: | Boost 1.57.0 | Severity: | Regression |
Keywords: | next, prior, advance, iterator, category, type_traits, has_plus_assign, forward_iterator | Cc: | raad@…, Andrey.Semashev@… |
Description
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)
Change History (4)
comment:1 by , 7 years ago
comment:2 by , 7 years ago
Cc: | added |
---|
comment:3 by , 7 years ago
Cc: | added |
---|
comment:4 by , 5 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
For the same reason, boost::next is broken with std::reverse_iterator (tested with GCC libstdc++ 5.1)