迭代std :: variant的映射

Flu*_*ffy 2 c++ variant c++17

我正在尝试使用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;
};
Run Code Online (Sandbox Code Playgroud)

这种启发式方法是获取每个声明类型的映射值,如:

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

这有效,但感觉它并不意味着存在.
可以std::variant用于此吗?从一开始就是一个坏主意,我应该使用继承和vo吗?

Sto*_*ica 8

可以std::variant用于此吗?

是.您的代码已准备好有效地使用变体.变体保存具有相同隐式接口的类型.这是std::visit与通用lambda 一起使用的绝佳机会.

void MyClass::cycleThroughMap() {
    for (auto& [ key, control ] : controlMap) {
        std::visit([](auto&& c) {
          c.doStuff();
        }, control);
    }
}
Run Code Online (Sandbox Code Playgroud)

我还冒昧地用结构化绑定替换了对访问.为了一些简单的增加.