
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 ); }