2010/12/9 Hicham Mouline <hicham@mouline.org>
struct S {
 virtual ~S()
 {}
};
struct Deriv1 : public S {
 virtual ~Deriv1()
 {}
};
struct Deriv2 : public S {
 virtual ~Deriv2()
 {}
};
struct Deriv3 : public Deriv2 {
 virtual ~Deriv3()
 {}
};

typedef boost::variant<S,Deriv1, Deriv2, Deriv3> my_variant_t;
typedef boost::mpl::sort<my_variant_t::types, boost::mpl::not_<boost::is_base_and_derived<boost::mpl::_,boost::mpl::_> > >::type v0_sorted_t;


template <typename Variant, typename Base>
struct assign {
 assign(Variant& v, const Base& b)
   : v_(v), assigned_(false), b_(b)
 {}

 template <typename T>
 void operator()(const T&)
 {
   std::cout<< typeid(T).name() <<std::endl;
   if (!assigned_) {
     const T* t = dynamic_cast<const T*>(&b_);
     if (t!=0) {
       v_ = (*t);
       assigned_ = true;
     }
   }
 }
private:
 Variant& v_;
 bool assigned_;
 const Base& b_;
};


int main()
{
 S s; Deriv1 d1; Deriv2 d2; Deriv3 d3;

 const S& base = s;

 my_variant_t vvv;
 boost::mpl::for_each<v0_sorted_t>( assign<my_variant_t,S>(vvv, base) );

 std::cout<< vvv.which() <<std::endl;
 return 0;
}

A thought: won't the following minor design change simplify things? I think You can avoid sorting the types by introducing struct Deriv0 : S to be used wherever objects of class S were used. While You're at it, You can make S an abstract base ;-)

Regards, Kris