boost::optional is a great utility. I find more and more uses for it everywhere. However I've started to realize that it is a more general tool that currently thought. I've been reading about Monads and looking a little at Haskell and Scala. For our purposes I like the concept that a Monad is a container or at least container like. It is a type that wraps another type. Generally there are multiple instances of the inner type wrapped by the outer type.

So what exactly is boost::optional. Well it behaves a little bit like a container that can contain exactly 0 or 1 elements. However boost::optional does not support the container concepts like all the other containers. More specifically it doesn't support the range concepts. Would it be nice to do something like

void foo(boost::optional<int> opt_v){
    BOOST_FOREACH(const int & v, opt_v){
        cout << v;
    }
}

You may say that this is redudant as we could just have easily written.

void foo(boost::optional<int> opt_v){
    if (opt_v){
        cout << v;
    }
}

but that is missing the point. Bring in the new range adaptor library introduced in boost 1.43 and then you can start to do fun things.

int plus(const int & i){
    return i + 1;
}

void foo(boost::optional<int> opt_v){
    boost::copy
        ( opt_v | transformed(plus)
        , std::ostream_iterator<int>(std::cout)
        );
}

The output of

foo(10)

will be

11

The neat thing is that I have never explicity tested the parameter optv to see if it valid or boost::none. Treating optv as a boost::range allows me to compose functionality easier than I would have.

The implementation is not so complicated. boost::range provides all the boilerplate you really need.

#include "boost/optional.hpp"
#include "boost/range.hpp"
#include <boost/iterator/iterator_facade.hpp>


template<typename T>
class optional_iterator
  : public boost::iterator_facade
      < optional_iterator<T>
      , T
      , boost::forward_traversal_tag
      , const T & 
      , std::ptrdiff_t
      >
{
 public:
    optional_iterator()
      : mVal(NULL),
      done(true)
    {}

    explicit optional_iterator(boost::optional<T> const & opt)
      : mVal(&opt)
      , done(opt == false)
    {}

    optional_iterator<T> & operator++(){
        done = true;
        return *this;
    }

    T const & operator*() const{
        return **mVal;
    }
    T const & operator*() {
        return **mVal;
    }

    bool equal(optional_iterator const & other) const{
        return ((done && other.done) ||
           ( mVal == other.mVal && done == other.done));
    }

 private:
    const boost::optional<T> * mVal;
    bool done;
};


namespace boost
{
    //
    // The required functions. These should be defined in
    // the same namespace as 'Pair', in this case 
    // 
    // in namespace 'Foo'.
    //

    template< class T >
    inline optional_iterator<T> range_begin( boost::optional<T>& x )
    { 
        return optional_iterator<T>(x);
    }

    template< class T >
    inline optional_iterator<T> range_begin( const boost::optional<T>& x )
    { 
        return optional_iterator<T>(x);
    }

    template< class T >
    inline optional_iterator<T> range_end( boost::optional<T>& x )
    { 
        return optional_iterator<T>();
    }

    template< class T >
    inline optional_iterator<T> range_end( const boost::optional<T>& x )
    { 
        return optional_iterator<T>();
    }

}

template<typename T>
inline boost::mpl::true_ *
boost_foreach_is_lightweight_proxy(boost::optional<T> *&, boost::foreach::tag) { return 0; }

namespace boost
{

    template<typename T>
    struct range_mutable_iterator< boost::optional<T> >
    {
        typedef optional_iterator<T> type;
    };

    template<typename T>
    struct range_const_iterator< boost::optional<T> >
    {
        typedef optional_iterator<T> type;
    };
}

So in summary. boost::range can be for more than just wrapping containers. Things you might not obviously see as a range can be adapted and then be used with the new range adaptor.