【发布时间】:2018-05-07 08:35:11
【问题描述】:
我正在尝试使用 C++17 的 std::variant 在地图中存储多种类型的数据。这里的用例是拥有一个泛型类型控制器的映射(但受std::variant 约束),我可以遍历并调用其方法。
在下面的例子中,
#include <iostream>
#include <map>
#include <variant>
class ControlA {
public:
void specificToA() { std::cout << "A" << std::endl; }
};
class ControlB {
public:
void specificToB() { std::cout << "B" << std::endl; }
};
template<typename T>
class ControlItem{
T* control;
public:
ControlItem() = default;
~ControlItem() = default;
void doStuff() {
if constexpr (std::is_same_v<T, ControlA>) {
control->specificToA();
}
if constexpr (std::is_same_v<T, ControlB>) {
control->specificToB();
}
}
};
class MyClass {
public:
void cycleThroughMap();
std::map<std::string, std::variant<ControlItem<ControlA>, ControlItem<ControlB>>> controlMap;
};
启发式方法是获取每个声明类型的映射值,例如:
void MyClass::cycleThroughMap() {
for (auto controlItem : controlMap) {
if (auto control = std::get_if<ControlItem<ControlA>>(&controlItem.second)) {
control->doStuff();
} else if (auto control = std::get_if<ControlItem<ControlB>>(&controlItem.second)) {
control->doStuff();
} else
std::cout << "Unknown type!" << std::endl;
}
}
这可行,但感觉它不应该存在。std::variant 可以用于此目的吗?从一开始就不是一个坏主意,我应该使用继承吗?
【问题讨论】:
-
如果你还是调用了同一个函数,为什么要从检查开始呢?您还可以通过将
specificTo函数命名为相同来摆脱doStuff中的检查。也许对ControlA和ControlB使用继承和多态性来给它们一个固定的接口? -
是的,直截了当的方法就是这样,我试图了解 c++17 的功能将添加到我的项目中 - 感觉这个例子适合实验(尽管可能因为明显的多态感觉而令人困惑)
-
[OT]:
T* control;未初始化使用。