You can use the following wrapper:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/functional/hash.hpp>
template<typename T>
class maybe
{
public:
maybe():impl(boost::make_shared<int>(0)){}
maybe(const T& t):impl(t){}
bool empty()const{return impl.which()==0;}
T& get(){return boost::get<T>(impl);}
const T& get()const{return boost::get<T>(impl);}
friend bool operator==(const maybe& x,const maybe& y){return x.impl==y.impl;}
friend std::size_t hash_value(const maybe& x){return boost::hash<impl_type>()(x.impl);}
private:
typedef boost::variant<boost::shared_ptr<void>,T> impl_type;
impl_type impl;
};
...
maybe<int> x=5;
maybe<int> y; // empty
maybe<int> z; // empty
The nice thing about maybe
is that empty values are different (that, is, !(y==z)
in the example), so you can keep your Boost.MultiIndex indices unique.