与传统的多态处理相比,使用std :: variant有什么优势?

时间:2018-09-12 13:54:14

标签: c++ variant boost-variant

假设我有一个Shape基类和CircleLinePoint派生类。我有两个功能。

std::variant<Circle, Line, Point> process(const Shape &s);
Shape process(const Shape& s);

我可以传入我的任何派生类并在第二个函数中返回Shape对象,而变量只是一个联合,可以在任何给定时间保存我的任何派生类变量。

现在使用std::variant,我也可以使用visitor,在这里我可以根据变量当前所持的类型来处理某些函数(我可以创建一个函数对象并将其传递给{{1} }并将其应用于我的每个对象)。但是,我只可以在基类中创建该函数std::transform并让每个派生类实现它。

那么virtual只是一个方便吗?

2 个答案:

答案 0 :(得分:4)

  

那么,变体只是一种方便吗?

不,它们是不同的概念。一方面std::variant可以与不相关的类型(包括像int这样的内建函数一起使用)的主要区别在于,直接使用虚函数是不可能的。另一方面,std::variant必须在编译时知道它正在使用的类型。例如,可以通过以下方式添加带有虚函数的类型:仅链接其他对象模块,而无需重新编译其余代码或将共享库动态加载到现有应用程序(甚至不必重新启动应用程序),而使用{ {1}},您必须重新编译处理类型为std::variant的代码。

答案 1 :(得分:2)

  

但是,我只能在基类中将该函数虚拟化,并让每个派生类实现它。

是的...。如果variant中的所有元素都共享一个公共基数(Slava already mentioned)。

另一个巨大的区别是,使用variant,在访问过程中根本没有任何动态多态发生(不需要RTTI)。

结合std::visit,有很多技巧可以确保在为给定的std::variant调用适当的函数时,(基本上)运行时开销为零。尽管可能会产生大量琐碎的编译时间和内存使用量,因为它通过创建大型函数指针矩阵(See this excellent blog post from Michael Park来实现)