Re: [Boost-users] variant over base and derived classes

-----Original Message----- From: "Hicham Mouline" [hicham@mouline.org] Date: 09/12/2010 03:22 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] variant over base and derived classes
-----Original Message----- From: "Diederick C. Niehorster" [dcnieho_at_[hidden]] Date: 09/12/2010 01:51 PM To: boost-users_at_[hidden] Subject: Re: [Boost-users] variant over base and derived classes (sorry if this is a top post, my phone shows no msg quotes) I'm no expert on this, but isn't there an compile time function to testing if an instance is derived from another (in introspection or something)? You could then maybe sort the variant types for most to least derived and then test untill you find the suitable cast? Just brainstorming pretty much. Hope its useful! Best, Dee yes, there is boost::is_base_of or some metafct like that in type_traits. not quite sure how to implement the sort though? will checkout mpl::sort with binary predicate base_or_derived. I have under 10 types, so compile time should be ok thanks,
This works. The source is pasted below. I am however obliged to 1. declare a default-constructed variant 2. call mpl::for_each on the sequence of types in the variant a assign functor to assign to the variant. Is there a way I can embed/simplify this 2 stage construction? regards, Here is the source :-) #include <iostream> #include <boost/variant.hpp> #include <boost/type_traits/is_base_and_derived.hpp> #include <boost/mpl/sort.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/lambda.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/not.hpp> #include <boost/mpl/logical.hpp> 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; }

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
participants (2)
-
Hicham Mouline
-
Krzysztof Czainski