Baz
Baz

Reputation: 13125

Understanding boost::variant

Why wouldn't the following compile:

void f(int8_t a)
{
}

void f(int16_t a)
{
}

typedef boost::variant<int8_t, int16_t> AttrValue;

int main()
{
    AttrValue a;
    a = int8_t(1);
    f(a);
}

With the compiler error:

error C2665: 'f' : none of the 2 overloads could convert all the argument types
could be 'void f(int8_t)'
or 'void f(int16_t)'

However, this is OK:

std::cout << a; // f(a);

Where is Where is std::ostream &operator<<(std::ostream &, const AttrValue &) defined and why is it defined?

Upvotes: 3

Views: 886

Answers (3)

Gorpik
Gorpik

Reputation: 11028

It happens that operator<< is defined for boost::variant, so the compiler does not need to perform any implicit type conversion. For your f() function, on the other hand, it does not know which conversion to select.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409146

Well, for one thing you are assigning a to itself. And since none of the overloads take a boost::variant type then of course the compiler can't find the correct function.

Also, you may have to use boost::get to get value:

f(boost::get<int8_t>(a));

Upvotes: 2

ecatmur
ecatmur

Reputation: 157324

Overload resolution happens at compile time, when your boost::variant instance could contain either type, so the compiler has no way of knowing whether to call void f(int8_t) or void f(int16_t).

std::cout << a works because in either case it's calling the same function, std::ostream &operator<<(std::ostream &, const AttrValue &), which inside dispatches on the runtime type of the instance.

You need to write a visitor to perform the dispatching:

struct f_visitor: public boost::static_visitor<void>
{
    template<typename T> void operator()(T t) const { return f(t); }
};

boost::apply_visitor(f_visitor(), a);

Upvotes: 9

Related Questions