Reputation: 13125
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
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
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
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