Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling methods common to types in a boost::variant

If all the types in my boost::variant support the same method, is there a way to call it generically (i.e. not calling it seperately for each method of the static_visitor)?

I'm trying to get something like this to work:

class A
{
    void boo() {}
};

class B
{
    void boo() {}
};

class C
{
    void boo() {}
};

typedef boost::variant<A, B, C> X;

void foo(X& d)
{
    x.boo();
}

but it fails to compile saying 'boo' : is not a member of 'boost::variant<T0_,T1,T2>'.

Currently, I have some classes all inherit from an interface so that their single shared method can be used polymorphically. I also want to be able to use the classes via a visitor as all other methods are unique to each concrete class. I was hoping boost::variant might be a better alternative to implementing my own visitor mechanism here. Is it?

like image 806
thehouse Avatar asked Jun 20 '12 00:06

thehouse


People also ask

What is boost variant?

boost::variant is defined in boost/variant. hpp . Because boost::variant is a template, at least one parameter must be specified. One or more template parameters specify the supported types. In Example 24.1, v can store values of type double , char , or std::string .

What is boost any?

The boost::any class (based on the class of the same name described in "Valued Conversions" by Kevlin Henney, C++ Report 12(7), July/August 2000) is a variant value type based on the second category. It supports copying of any value type and safe checked extraction of that value strictly against its type.


1 Answers

There's no direct way, but you can make the static_visitor pretty concise using templating.

Modified from the boost docs:

struct boo_generic : public boost::static_visitor<>
{
    template <typename T>
    void operator()( T & operand ) const
    {
        operand.boo();
    }
};

Now you can do this:

boost::apply_visitor( boo_generic(), v );

Infact you can generalise this to take a function pointer of your base class:

struct fn_generic : public boost::static_visitor<>
{
   fn_generic( void (IBase::fn)() ) : fn_(fn) {}
   template<T> void operator() ( T & op ) const { op.*fn(); }
}

Then you can do:

boost::apply_visitor( boo_generic( IBase::boo ), v );

Or something like that - I've probably got my function pointer syntax wrong, but hopefully you get the idea.

like image 107
Michael Anderson Avatar answered Sep 30 '22 08:09

Michael Anderson