如何访问 `std::variant` 的任何 child 的 `polymorphic` 基 class?
How to access the `polymorphic` base class for any child of an `std::variant`?
假设有几个 child class 用于一个基数 class:
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 {};
假设一个变体包含任何包含的 classes:
using MyVariant = std::variant<Base, Child1, Child2, Child3, ... ChildN>;
Note: The interest of this (compared to a simple vector of polymorphic
pointers), is to have all the data in the same memory array, because
they are going to be transferred to a device. In this case, the real
content of each object is in the vector, not only a pointer to some
heap
position.
最后,假设我想使用 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();
}
Note: Obviously, the trivial solution of having an if
statement for each types is not the intention, because new child classes could be added to MyVariant
without having to change all further usages. (Extensibility)
所以表达问题的另一种方式是:
如何在 std::variant 中管理多态性?
将 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
假设有几个 child class 用于一个基数 class:
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 {};
假设一个变体包含任何包含的 classes:
using MyVariant = std::variant<Base, Child1, Child2, Child3, ... ChildN>;
Note: The interest of this (compared to a simple vector of polymorphic pointers), is to have all the data in the same memory array, because they are going to be transferred to a device. In this case, the real content of each object is in the vector, not only a pointer to some
heap
position.
最后,假设我想使用 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();
}
Note: Obviously, the trivial solution of having an
if
statement for each types is not the intention, because new child classes could be added toMyVariant
without having to change all further usages. (Extensibility)
所以表达问题的另一种方式是:
如何在 std::variant 中管理多态性?
将 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