与传统的多态处理相比,使用 std::variant 有什么优势?
What are the advantages of using std::variant as opposed to traditional polymorphic processing?
假设我有一个 Shape
基础 class 和 Circle
、Line
和 Point
派生的 classes。我有两个功能。
std::variant<Circle, Line, Point> process(const Shape &s);
Shape process(const Shape& s);
我可以在第二个函数中传入我派生的任何 classes 和 return 一个 Shape 对象,变体只是一个联合体,它可以包含我派生的任何 class 任何给定时间的变量。
现在使用 std::variant
我还可以使用 visitor
来处理一些函数,具体取决于我的变体当前持有的类型(我可以创建一个函数对象并传递它 std::transform
并将其应用于我的每个对象)。但是,我可以在我的基础 class 中创建该函数 virtual
并让每个派生 class 实现它。
那么,variant
只是为了方便吗?
So, is variant just a convenience?
不,它们是不同的概念。主要区别在于,一方面 std::variant
可以使用不相关的类型,包括像 int
这样的内置函数,这不能直接使用虚函数。另一方面 std::variant
必须知道它在编译时使用的类型。例如,可以通过链接额外的对象模块来添加具有虚函数的类型,而无需重新编译其余代码或将共享库动态加载到现有应用程序(您甚至不必重新启动应用程序),同时使用 std::variant
您必须重新编译处理类型 std::variant
包含的代码。
However, I can just make that function virtual in my base class and have each derived class implement it.
是....如果 variant
中的所有元素共享一个公共基础()。
另一个很大的区别是,对于 variant
,在访问期间根本没有必要 任何 动态多态性发生(不需要 RTTI)。
与 std::visit
相结合,有很多技巧可以确保在为给定的 std::variant
调用适当的函数时(基本上)运行时开销为零。虽然可能会有不平凡的额外编译时间和内存使用,因为它是通过创建一个大的函数指针矩阵来实现的(See this excellent blog post from Michael Park 关于它)
假设我有一个 Shape
基础 class 和 Circle
、Line
和 Point
派生的 classes。我有两个功能。
std::variant<Circle, Line, Point> process(const Shape &s);
Shape process(const Shape& s);
我可以在第二个函数中传入我派生的任何 classes 和 return 一个 Shape 对象,变体只是一个联合体,它可以包含我派生的任何 class 任何给定时间的变量。
现在使用 std::variant
我还可以使用 visitor
来处理一些函数,具体取决于我的变体当前持有的类型(我可以创建一个函数对象并传递它 std::transform
并将其应用于我的每个对象)。但是,我可以在我的基础 class 中创建该函数 virtual
并让每个派生 class 实现它。
那么,variant
只是为了方便吗?
So, is variant just a convenience?
不,它们是不同的概念。主要区别在于,一方面 std::variant
可以使用不相关的类型,包括像 int
这样的内置函数,这不能直接使用虚函数。另一方面 std::variant
必须知道它在编译时使用的类型。例如,可以通过链接额外的对象模块来添加具有虚函数的类型,而无需重新编译其余代码或将共享库动态加载到现有应用程序(您甚至不必重新启动应用程序),同时使用 std::variant
您必须重新编译处理类型 std::variant
包含的代码。
However, I can just make that function virtual in my base class and have each derived class implement it.
是....如果 variant
中的所有元素共享一个公共基础(
另一个很大的区别是,对于 variant
,在访问期间根本没有必要 任何 动态多态性发生(不需要 RTTI)。
与 std::visit
相结合,有很多技巧可以确保在为给定的 std::variant
调用适当的函数时(基本上)运行时开销为零。虽然可能会有不平凡的额外编译时间和内存使用,因为它是通过创建一个大的函数指针矩阵来实现的(See this excellent blog post from Michael Park 关于它)