Boost logo

Boost Users :

Subject: Re: [Boost-users] Using single-pass ranges.
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2012-08-03 13:07:38


> When a range is constructed from a 'getNextThing()' sort of interface,
> it seems quite
> reasonable for that interface to return references to an abstract type.
> However that doesn't
> seem to be supported by Boost.IteratorFacade. I guess this only comes
> up in this context,
> as you couldn't construct a container of abstract objects, but is this
> a know limitation of
> iterator_facade?

I'm not sure whether this can be done with iterator_facade. If not,
Boost.Iterator could probably use a new utility (abstract_iterator_facade?)
that makes this possible.

As a workaround, though, you can make ThingRange be a range of pointers
instead. See code below.

Regards,
Nate

#include <iostream>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/filtered.hpp>

struct AbstractThing {
    virtual char get_c( ) const = 0;
    virtual ~AbstractThing( ) { }
};

struct Thing : AbstractThing {
    Thing( char c ) : c( c ) { }
    char get_c( ) const { return c; }
private:
    char c;
};

struct ThingFeed
{
    ThingFeed( const char * thing_values ) : m_current_value( thing_values ) { }
    AbstractThing * getNextThing( ) { return * m_current_value ? new Thing( * m_current_value ++ ) : 0; }
private:
    const char * m_current_value;
};

struct ThingIterator : public boost::iterator_facade<ThingIterator, AbstractThing *, boost::single_pass_traversal_tag, AbstractThing *>
{
   ThingIterator( ThingFeed & feed, AbstractThing * cur = NULL ) : m_feed( feed ), m_cur( cur ) {}

   bool equal( const ThingIterator & other ) const { return m_cur == other.m_cur; }
   void increment( ) { m_cur = m_feed.getNextThing( ); }
   AbstractThing * dereference( ) const { return m_cur; }

private:

   ThingFeed & m_feed;
   AbstractThing * m_cur;
};

struct ThingRange : public boost::iterator_range<ThingIterator>
{
    ThingRange( ThingFeed & feed )
        : boost::iterator_range<ThingIterator>(
             ThingIterator( feed, feed.getNextThing( ) ),
             ThingIterator( feed ) )
    {}
};

void printThing( const AbstractThing * thing ) { std::cout << thing->get_c( ) << "\n"; }

int main( )
{
    ThingFeed feed( "abcd" );
    boost::for_each( ThingRange(feed), printThing );
}

                                               


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net