如何访问`std::variant`的任何孩子的`polymorphic`基类?
Posted
技术标签:
【中文标题】如何访问`std::variant`的任何孩子的`polymorphic`基类?【英文标题】:How to access the `polymorphic` base class for any child of an `std::variant`? 【发布时间】:2019-10-06 09:53:15 【问题描述】:假设一个基类有几个子类:
class Base
public:
void printHello() const cout << "Hello" << endl;
;
class Child1: public Base ;
class Child2: public Base ;
class Child3: public Base ;
..
class ChildN: public Base ;
假设一个变体包含任何包含的类:
using MyVariant = std::variant<Base, Child1, Child2, Child3, ... ChildN>;
注意:这个的兴趣(相比于一个简单的多态向量 指针),是将所有数据放在同一个内存数组中,因为 它们将被转移到设备上。在这种情况下,真正的 每个对象的内容都在向量中,而不仅仅是指向某些对象的指针
heap
位置。
最后,假设我想使用vector<MyVariant>
的每个元素的Base
多态版本。
std::vector<MyVariant> myVariantList;
... // Initialization
for (const MyVariant& elem: myVariantList)
const Base* baseElem = get_if_polymorph<Base>(elem); //HOW TO?
baseElem->printHello();
注意:显然,为每种类型添加
if
语句的简单解决方案不是意图,因为可以将新的子类添加到MyVariant
无需更改所有进一步的用法。 (可扩展性)
所以另一种表达问题的方式是:
如何管理 std::variant 中的多态性?
【问题讨论】:
非常好的问题。谢谢。 【参考方案1】:将std::visit
与通用 lambda 一起使用:
const Base& baseElem = std::visit(
[](const auto& x) -> const Base& return x; ,
elem);
最小的可重现示例:
#include <iostream>
#include <variant>
#include <vector>
struct Base
virtual void hi() const
std::cout << "Base\n";
;
struct Derived1 : Base
void hi() const override
std::cout << "Derived1\n";
;
struct Derived2 : Base
void hi() const override
std::cout << "Derived2\n";
;
int main()
using Var = std::variant<Base, Derived1, Derived2>;
std::vector<Var> elems;
elems.emplace_back(std::in_place_type<Base>);
elems.emplace_back(std::in_place_type<Derived1>);
elems.emplace_back(std::in_place_type<Derived2>);
for (const auto& elem : elems)
const Base& x = std::visit(
[](const auto& x) -> const Base& return x; ,
elem);
x.hi();
输出:
Base
Derived1
Derived2
(live demo)
【讨论】:
以上是关于如何访问`std::variant`的任何孩子的`polymorphic`基类?的主要内容,如果未能解决你的问题,请参考以下文章
使用类作为数据类型时如何在 std::variant 中存储值?
std::get_if (std::variant) 通过指针而不是值/&/const& 获取变体参数是不是有任何实际原因?
std::visit 无法推断 std::variant 的类型
如何将 std::variant 作为 VARIANT* 传递给 ExecWB?