将由 boost::variant 聚合的类型的对象传递给接受该 boost::variant 的函数
Posted
技术标签:
【中文标题】将由 boost::variant 聚合的类型的对象传递给接受该 boost::variant 的函数【英文标题】:Pass an object of a type aggregated by a boost::variant to a function that accepts that boost::variant 【发布时间】:2011-02-23 13:10:43 【问题描述】:假设我有:
class TypeA ;
class TypeB ;
typedef boost::variant<TypeA, TypeB> Type;
没关系:
void foo(Type t) ;
int main()
TypeA a;
foo(a);
这不会编译:
void foo(Type &t) ;
int main()
TypeA a;
foo(a);
出现错误:
“Type&”类型的引用初始化无效 “TypeA”类型的表达式
这也不编译:
void foo(Type *t) ;
int main()
TypeA a;
foo(&a);
出现错误:
无法将参数“1”的“TypeA*”转换为“Type*”到“void” foo(类型*)'
有没有办法通过引用(如案例 2)或指针(如案例3)?
非常感谢!
【问题讨论】:
【参考方案1】:1 中真正发生的事情:
TypeA a;
Type __temporary__(a);
foo(__temporary__);
2 或 3 中不可能发生的事情:
TypeA a;
Type* __temporary__(&a);
// this fails because there is no inheritance relationship
foo(__temporary__);
您有两种解决方案(对于非模板 foo):
转换为Type
,然后获取指向此的指针/引用
创建一个boost::variant<TypeA*,TypeB*>
以进行隐式转换
第三种解决方案是更改 foo 本身,并使其成为模板。这取决于你想做什么。
【讨论】:
谢谢!但是__temporary__
是什么意思?如果您的意思是编译器临时对象,那么它不会仅通过调用例如创建。 “富(类型A());” ?在您的第一个解决方案中,从 TypeA 到 Type 的转换是否需要副本,例如。如“TypeA a; Type t=a; foo(&t);” ?很好的第二个解决方案,我会考虑的!至于模板,我怎么能适应没有公共基类的不相关的TypeA和TypeB?
@Francesco:编译器将a
复制到Type
(变体)类型的临时对象中,然后使用此临时对象执行对foo
的调用。 // 模板适用于不相关的类型,只要两者都存在所需的方法。【参考方案2】:
聚合意味着boost::variant
包含TypeA
和TypeB
。它没有。它包含TypeA
或TypeB
。它更像是一个联合而不是一个结构。
您可以按值传递TypeA
,因为存在从TypeA
到Type
的隐式转换。
没有从TypeA&
到Type&
(或TypeA*
到Type*
)的隐式转换,也不应该存在。想想如果对 TypeA
对象的引用被传递到 foo()
并且 foo()
决定用 TypeB
值替换它会发生什么。
不知道foo()
和TypeA
/TypeB
是什么,我不能给你更具体的建议,但也许你可以使用函数模板。即
template <typename T>
void foo(T& t)
或重载函数:
void foo(TypeA& t)
void foo(TypeB& t)
【讨论】:
谢谢!重载函数可能是一个解决方案。至于模板,我怎么能适应没有公共基类的不相关的TypeA和TypeB? 模板不关心实际的参数类型。唯一重要的是,您对类型参数化对象执行的任何操作都对实际类型的对象有效。如果两种类型的代码相同,请使用模板。否则,重载函数可能是要走的路。以上是关于将由 boost::variant 聚合的类型的对象传递给接受该 boost::variant 的函数的主要内容,如果未能解决你的问题,请参考以下文章
如何返回由 boost::variant 返回类型中包含的类型的子集组成的 boost::variant
使用 boost::mpl 获取 boost::variant 的类型索引