Pass an object of a type aggregated by a boost::variant to a function that accepts that boost::variant
-
05-12-2019 - |
Domanda
Suppose I have:
class TypeA { };
class TypeB { };
typedef boost::variant<TypeA, TypeB> Type;
This is ok:
void foo(Type t) { }; int main(){ TypeA a; foo(a); }
This does not compile:
void foo(Type &t) { }; int main(){ TypeA a; foo(a); }
with the error:
invalid initialization of reference of type ‘Type&’ from expression of type ‘TypeA’
Also this does not compile:
void foo(Type *t) { }; int main(){ TypeA a; foo(&a); }
with the error:
cannot convert ‘TypeA*’ to ‘Type*’ for argument ‘1’ to ‘void foo(Type*)’
Is there a way to pass to a function that accepts a boost::variant an instance of one of the types aggregated by that boost::variant, either through a reference (as in case 2) or a pointer (as in case 3)?
Thank you very much!
Soluzione
What really happens in 1:
TypeA a;
Type __temporary__(a);
foo(__temporary__);
What cannot happen in 2 or 3:
TypeA a;
Type* __temporary__(&a);
// this fails because there is no inheritance relationship
foo(__temporary__);
You have two solutions (for a non template foo):
- convert to
Type
, then take a pointer/reference to this - create a
boost::variant<TypeA*,TypeB*>
for implicit conversion to kick in
A third solution is to change foo itself, and make it template. It depends on what you want to do.
Altri suggerimenti
Aggregation implies that the boost::variant
contains both TypeA
and TypeB
. It doesn't. It contains either TypeA
or TypeB
. It's more like a union than a struct.
You can pass TypeA
by value because there is an implicit conversion from TypeA
to Type
.
There is no implicit conversion from TypeA&
to Type&
(or TypeA*
to Type*
) and there shouldn't be. Think of what would happen if a reference to a TypeA
object was passed into foo()
and foo()
decides to replace it with a TypeB
value.
Without knowing what foo()
and TypeA
/TypeB
are, I can't give you more specific advice but perhaps you can use a function template. i.e.
template <typename T>
void foo(T& t) {}
or overloaded functions:
void foo(TypeA& t) {}
void foo(TypeB& t) {}