[Boost-bugs] [Boost C++ Libraries] #11287: adaptors: strided does not support input iterators

Subject: [Boost-bugs] [Boost C++ Libraries] #11287: adaptors: strided does not support input iterators
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-05-12 08:08:18


#11287: adaptors: strided does not support input iterators
---------------------------------------------+------------------------
 Reporter: Akim Demaille <akim.demaille@…> | Owner: neilgroves
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: range
  Version: Boost 1.58.0 | Severity: Problem
 Keywords: |
---------------------------------------------+------------------------
 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';
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/11287>
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:18 UTC