C++ 遍历std::variant的映射
我正在试验用C++17在地图中存储多种类型的数据。这里的用例是有一个泛型类型的控制器的映射(但是由C++ 遍历std::variant的映射,c++,c++17,variant,C++,C++17,Variant,我正在试验用C++17在地图中存储多种类型的数据。这里的用例是有一个泛型类型的控制器的映射(但是由std::variant绑定),我可以遍历它并调用它的方法。 在下面的例子中 #include <iostream> #include <map> #include <variant> class ControlA { public: void specificToA() { std::cout << "A" << std::en
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 specificToA(){std::cout doStuff();
}否则
标准::cout
std::variant
可以用于此目的吗
是的。您的代码已经准备好有效地使用变体。变体包含具有相同隐式接口的类型。这是一个与通用lambda一起使用的绝佳机会
void MyClass::cycleThroughMap() {
for (auto& [ key, control ] : controlMap) {
std::visit([](auto&& c) {
c.doStuff();
}, control);
}
}
我还冒昧地用结构化绑定替换了pair访问。为了更加简单。另一种构造代码的方法-不需要get_if。注释内联:
#include <map>
#include <variant>
#include <iostream>
class ControlA {
public:
void specificToA() { std::cout << "A" << std::endl; }
};
// consistent free-function interface for each operation type allows ADL lookup
void adlDoStuff(ControlA& c)
{
// but with different implementation details
c.specificToA();
}
class ControlB {
public:
void specificToB() { std::cout << "B" << std::endl; }
};
// consistent free-function interface for each operation type allows ADL lookup
void adlDoStuff(ControlB& c)
{
// but with different implementation details
c.specificToB();
}
template<typename T>
class ControlItem{
T* control;
public:
ControlItem() = default;
~ControlItem() = default;
void doStuff() {
// invoke the adl-friendly free functions.
adlDoStuff(*control);
}
};
class MyClass {
public:
void cycleThroughMap();
std::map<std::string, std::variant<ControlItem<ControlA>, ControlItem<ControlB>>> controlMap;
};
void MyClass::cycleThroughMap() {
// use std::visit. Every type of control will have the .doStuff interface
for (auto&& elem : controlMap) {
std::visit([](auto&& control)
{
control.doStuff();
}, elem.second);
}
}
#包括
#包括
#包括
控制类{
公众:
void specificToA(){std::cout如果你调用的是同一个函数,为什么要开始检查呢?你也可以通过将specificTo
函数命名为相同的函数来取消签入doStuff
。也许可以对ControlA
和ControlB
使用继承和多态性来给它们一个固定的接口?是的strai直接的方法就是,我正试图了解c++17的特性会给我的项目增加什么——感觉这个例子适合实验(尽管可能会因为它明显的多态性而混淆)[OT]<代码> t*控件;< /COD>未初始化。HA,正是我所要寻找的;这是C++初学者初学者不会想到的一些东西。完美无瑕,谢谢!
#include <map>
#include <variant>
#include <iostream>
class ControlA {
public:
void specificToA() { std::cout << "A" << std::endl; }
};
// consistent free-function interface for each operation type allows ADL lookup
void adlDoStuff(ControlA& c)
{
// but with different implementation details
c.specificToA();
}
class ControlB {
public:
void specificToB() { std::cout << "B" << std::endl; }
};
// consistent free-function interface for each operation type allows ADL lookup
void adlDoStuff(ControlB& c)
{
// but with different implementation details
c.specificToB();
}
template<typename T>
class ControlItem{
T* control;
public:
ControlItem() = default;
~ControlItem() = default;
void doStuff() {
// invoke the adl-friendly free functions.
adlDoStuff(*control);
}
};
class MyClass {
public:
void cycleThroughMap();
std::map<std::string, std::variant<ControlItem<ControlA>, ControlItem<ControlB>>> controlMap;
};
void MyClass::cycleThroughMap() {
// use std::visit. Every type of control will have the .doStuff interface
for (auto&& elem : controlMap) {
std::visit([](auto&& control)
{
control.doStuff();
}, elem.second);
}
}