Search code examples
c++boostpolymorphismboost-variantbounded-types

How to iterate through a sequence of bounded types with Boost.Variant


  struct A
  {
    std::string get_string();
  }; 

  struct B
  {
    int value;
  }; 

  typedef boost::variant<A,B> var_types;
  std::vector<var_types> v;

  A a;
  B b;

  v.push_back(a);
  v.push_back(b);

How can I iterate iterate through the elements of v to get access to the a and b objects ?

I'm able to do it with boost::get but the syntax is really cumbersome.:

std::vector<var_types>:: it = v.begin();
while(it != v.end())
{
    if(A* temp_object = boost::get<A>(&(*it)))    
      std::cout << temp_object->get_string();
    ++it;
}

I've tried to use the visitation technique but I didn't get too far and the code is not working :

template<typename Type>
class get_object
  : public boost::static_visitor<Type>
{
public:

  Type operator()(Type & i) const
  {
    return i;
  }

};

...

while(it != v.end())
{
    A temp_object = boost::apply_visitor(get_object<A>(),*it);
    ++it;
}

EDIT 1

A hackish solution is :

class get_object
  : public boost::static_visitor<A>
{
public:

  A operator()(const A & i) const
  {
    return i;
  }

  A operator()(const B& i) const
  {
    return A();
  }        
};

Solution

  • Edit:
    If it's as UncleBens suggests, then you can simply do this:

    BOOST_FOREACH(var_types& vt, v) {
        if (vt.which() == 0)  
            cout << get<A>(vt).get_string() << endl;
    }
    

    Original:
    The template parameter for static_vistor is the return type of its methods. This means the two classes need to share a common return type for a single visitor. It should look something like this:

    class ABVisitor : public static_visitor<string> {
    public:
        string operator()(const A& a) const {
            return a.get_string();
        }
        string operator()(const B& b) const {
            return lexical_cast<string>(b.value);
        }
    };
    

    Here's an example of iteration using this visitor.

    BOOST_FOREACH(var_types& vt, v)
        cout << apply_visitor(ABVisitor(), vt) << endl;