On Wed, Jul 25, 2012 at 5:13 AM, Nathan Ridge <zeratul976@hotmail.com> wrote:

Here's how you might do such a thing (untested):


Hi Nathan

That may be untested, but basically worked as is! All I had to do was adjust the
access on equal(), increment() & dereference() and it worked perfectly. 

Full code attached, built with Boost 1.47 and gcc-4.6.2, many thanks.

Rob.

#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 Thing { Thing( char c ) : c( c ) { } char c; };

std::ostream & operator << ( std::ostream & ostrm, const Thing & thing ) { return ostrm << thing.c; }

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

struct ThingIterator : public boost::iterator_facade<ThingIterator, Thing, boost::single_pass_traversal_tag>
{
   ThingIterator(ThingFeed& feed, Thing* 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(); }
   Thing& dereference() const { return *m_cur; }

private:

   ThingFeed& m_feed;
   Thing* m_cur;
};

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

void printThing( const Thing & thing ) { std::cout << thing << "\n"; }

bool thingFilter( const Thing & thing ) { return thing.c != 'c'; }

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