Question

I was trying boost-variant with custom classes. I understood that a safe way to access the content of a class is using boost::static_visitor. Do you know why the code below doesn't compile? Are there any requirement on the signature/declaration of boost::static_visitor in order to be used?

I found this question Why can't I visit this custom type with boost::variant? but I didn't get it.

Regards

AFG

#include <iostream>
#include <algorithm>
#include <boost/variant.hpp>

struct CA{};

struct ca_visitor : public boost::static_visitor<CA>
{
    const CA& operator()(const CA& obj ) const { return obj;}
};

struct CB{};

struct cb_visitor : public boost::static_visitor<CB>
{
    const CB& operator()(const CB& obj) const { return obj;}
};

int main(){   
    typedef  boost::variant< 
        CA  
        ,CB >  v_type;

    v_type v;
    const CA& a = boost::apply_visitor( ca_visitor(), v );
}
Was it helpful?

Solution

First of all, the template argument of boost::static_visitor<> should specify the type returned by the call operator. In your case, ca_visitor's call operator returns a CA const&, not a CA.

But that is not the biggest issue. The biggest issue is that you seem to have a misconception of how variant<> and static_visitor<> should work.

The idea of a boost::variant<> is that it can hold values of any of the types you specify in the template argument list. You don't know what that type is, and therefore you provide a visitor with several overloaded call operators for handling each possible case.

Therefore, when you provide a visitor, you need to make sure it has all necessary overloads of operator() that accept the types your variant can hold. If you fail to do so, Boost.Variant causes a compilation error to be generated (and is doing you a favor, because you forgot to handle some cases).

This is the issue you are facing: your visitor does not have a call operator accepting an object of type CB.

This is an example of a correct use of boost::variant<> and static_visitor<>:

#include <iostream>
#include <algorithm>
#include <boost/variant.hpp>

struct A{};
struct B{};

struct my_visitor : public boost::static_visitor<bool>
//                                               ^^^^
//                                               This must be the same as the
//                                               return type of your call 
//                                               operators
{
    bool operator() (const A& obj ) const { return true; }
    bool operator() (const B& obj) const { return false; }
};

int main()
{
    A a;
    B b;
    my_visitor mv;

    typedef boost::variant<A, B> v_type;

    v_type v = a;

    bool res = v.apply_visitor(mv);
    std::cout << res; // Should print 1

    v = b;

    res = v.apply_visitor(mv);
    std::cout << res; // Should print 0
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top