Opened 7 years ago
#11287 new Bugs
adaptors: strided does not support input iterators
Reported by: | Owned by: | Neil Groves | |
---|---|---|---|
Milestone: | To Be Determined | Component: | range |
Version: | Boost 1.58.0 | Severity: | Problem |
Keywords: | Cc: |
Description
Hi,
Despite what the documentation says, the stride adaptor does not support input iterators. This is a pity, since for instance its applicability to iterators to coroutines: see #11274.
Oliver Kowalke tracked down the issue, and built a small scale example that shows the problem: see http://lists.boost.org/boost-users/2015/05/84277.php. The example is repeated below:
#include <iostream> #include <iterator> #include <vector> #include <boost/range.hpp> #include <boost/range/adaptor/strided.hpp> namespace foo { template< typename T > class X { private: typedef std::vector< T > vec_t; vec_t vec_; public: X( vec_t const& vec) : vec_( vec) { } class iterator : public std::iterator< std::input_iterator_tag, T > { private: X * x_; typename vec_t::iterator i_; public: typedef typename iterator::pointer pointer_t; typedef typename iterator::reference reference_t; iterator() : x_( 0), i_() {} explicit iterator( X * x) : x_( x), i_( x_->vec_.begin() ) {} iterator( iterator const& other) : x_( other.x_), i_( other.i_) {} iterator & operator=( iterator const& other) { if ( this == & other) return * this; x_ = other.x_; i_ = other.i_; return * this; } bool operator==( iterator const& other) const { return other.x_ == x_ && other.i_ == i_; } bool operator!=( iterator const& other) const { return other.x_ != x_ || other.i_ != i_; } iterator & operator++() { ++i_; return * this; } iterator operator++( int) { i_++; return * this; } reference_t operator*() const { return * i_; } pointer_t operator->() const { return & ( * i_); } }; class const_iterator : public std::iterator< std::input_iterator_tag, const T > { private: X * x_; typename vec_t::const_iterator i_; public: typedef typename iterator::pointer pointer_t; typedef typename iterator::reference reference_t; const_iterator() : x_( 0), i_() {} explicit const_iterator( X * x) : x_( x), i_( x_->vec_.begin() ) {} const_iterator( const_iterator const& other) : x_( other.x_), i_( other.i_) {} const_iterator & operator=( const_iterator const& other) { if ( this == & other) return * this; x_ = other.x_; i_ = other.i_; return * this; } bool operator==( const_iterator const& other) const { return other.x_ == x_ && other.i_ == i_; } bool operator!=( const_iterator const& other) const { return other.x_ != x_ || other.i_ != i_; } const_iterator & operator++() { ++i_; return * this; } const_iterator operator++( int) { i_++; return * this; } reference_t operator*() const { return * i_; } pointer_t operator->() const { return & ( * i_); } }; friend class iterator; friend class const_iterator; }; template< typename T > typename X< T >::iterator range_begin( X< T > & c) { return typename X< T >::iterator( & c); } template< typename T > typename X< T >::const_iterator range_begin( X< T > const& c) { return typename X< T >::const_iterator( & c); } template< typename T > typename X< T >::iterator range_end( X< T > &) { return typename X< T >::iterator(); } template< typename T > typename X< T >::const_iterator range_end( X< T > const&) { return typename X< T >::const_iterator(); } template< typename T > typename X< T >::iterator begin( X< T > & c) { return boost::begin( c); } template< typename T > typename X< T >::const_iterator begin( X< T > const& c) { return boost::begin( c); } template< typename T > typename X< T >::iterator end( X< T > & c) { return boost::end( c); } template< typename T > typename X< T >::const_iterator end( X< T > const& c) { return boost::end( c); } } namespace boost { template< typename T > struct range_mutable_iterator< foo::X< T > > { typedef typename foo::X< T >::iterator type; }; template< typename T > struct range_const_iterator< foo::X< T > > { typedef typename foo::X< T >::const_iterator type; }; } int main() { std::vector< int > vec = { 1,2,3,4,5,6,7,8,9,10 }; auto x = foo::X< int >( vec); for (auto i : x | boost::adaptors::strided( 2) ) std::cout << i << " "; std::cout << '\n'; }
Note:
See TracTickets
for help on using tickets.