如何为`std :: variant`的任何子级访问`polymorphic`基类?

Adr*_*ire 4 c++ polymorphism inheritance variant c++17

假设一个基类有几个子类:

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 {};
Run Code Online (Sandbox Code Playgroud)

假设包含任何包含的类的变体:

using MyVariant = std::variant<Base, Child1, Child2, Child3, ... ChildN>;
Run Code Online (Sandbox Code Playgroud)

注意:与多态指针的简单向量相比,此方法的目的是将所有数据都存储在同一内存阵列中,因为它们将被传输到设备中。在这种情况下,每个对象的真实内容都在矢量中,而不仅仅是指向某个heap位置的指针 。

最后,假设我要使用Basea的每个元素的多态版本vector<MyVariant>

std::vector<MyVariant> myVariantList;
... // Initialization

for (const MyVariant& elem: myVariantList)
{
    const Base* baseElem = get_if_polymorph<Base>(elem); //HOW TO?
    baseElem->printHello();
}
Run Code Online (Sandbox Code Playgroud)

注意:显然,不是if要为每种类型都拥有一个语句的简单解决方案,因为可以添加新的子类而不必更改所有其他用法。(可扩展性)MyVariant

因此表达问题的另一种方法是:

如何在std :: variant中管理多态?

L. *_* F. 6

使用std::visit一个通用的拉姆达:

const Base& baseElem = std::visit(
    [](const auto& x) -> const Base& { return x; },
    elem);
Run Code Online (Sandbox Code Playgroud)

最小的可重现示例:

#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();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

const Base& baseElem = std::visit(
    [](const auto& x) -> const Base& { return x; },
    elem);
Run Code Online (Sandbox Code Playgroud)

现场演示