Boost logo

Boost Users :

Subject: Re: [Boost-users] variant over base and derived classes
From: Hicham Mouline (hicham_at_[hidden])
Date: 2010-12-09 10:36:12


 
 
-----Original Message-----
From: "Hicham Mouline" [hicham_at_[hidden]]
Date: 09/12/2010 03:22 PM
To: boost-users_at_[hidden]
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;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net