【问题标题】:How to access the `polymorphic` base class for any child of an `std::variant`?如何访问`std::variant`的任何孩子的`polymorphic`基类?
【发布时间】: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&lt;MyVariant&gt; 的每个元素的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 中的多态性?

【问题讨论】:

  • 非常好的问题。谢谢。

标签: c++ inheritance polymorphism c++17 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)

【讨论】:

    猜你喜欢
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多