id summary reporter owner description type status milestone component version severity resolution keywords cc 11287 adaptors: strided does not support input iterators Akim Demaille Neil Groves "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 #include #include #include #include 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'; } }}}" Bugs new To Be Determined range Boost 1.58.0 Problem