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