代码之家  ›  专栏  ›  技术社区  ›  Fluffy

访问并调用STD::

  •  4
  • Fluffy  · 技术社区  · 6 年前

    我用的是 std::variant 存储的不同签名 std::function 所述函数存储在矢量中,后者从地图中检索。

    如何调用向量中的每个函数 STD::变异型 ?我觉得我应该用 std::visit 但我无法找出正确的用法。

    #include <variant>
    #include <functional>
    #include <map>
    #include <iostream>
    #include <functional>
    
    using var_t = std::variant<std::function<void(void)>, std::function<void(int)>>;
    enum class EventEnum { A, B, C };
    
    struct Controller {
        template<EventEnum E>
        void subscribe(var_t fn) {
            auto& callbacksVec = callbacks.at(E);
            callbacksVec.push_back(fn);
        }
    
        template<EventEnum E>
        void notify() {
            auto& callbacksVec = callbacks.at(E);
            for (auto& func : callbacksVec) {
                // std::visit([](auto& arg){ std::invoke(arg); }, func);
            }
        }
    
        std::map<EventEnum, std::vector<var_t>> callbacks;
    };
    
    int main() {
        auto fn = []() { std::cout << "lambda callback" << std::endl; };
        Controller myController;
        myController.subscribe<EventEnum::A>(fn);
        myController.notify<EventEnum::A>();
    
        return 0;
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Rakete1111    6 年前

    std::visit 要求变量内的每个类型都具有有效的“action”。如果 func 我们有一个 std::function<void(int)> 而不是 std::function<void(void)> 就像现在这样,那就没有办法行动了。因为这(can)依赖于运行时, STD:访问 必须在编译时检查变量的每一个可能的选择都可以用来调用您的可调用变量。

    例如,可以将lambda合并在一起,或者 if constexpr 变量中每种类型的层叠。

    template<typename ...Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<typename ...Ts> overloaded(Ts...) -> overloaded<Ts...>;
    
    std::visit(overloaded{
        [](const std::function<void(void)> &Void) { std::invoke(Void); },
        [](const std::function<void(int)> &Int) { std::invoke(Int, 1); }}, func);
    
        2
  •  2
  •   Alexander Stepaniuk    6 年前

    下面是另一个例子,改编自 cppreference page 根据您的情况:

    #include <iomanip>
    #include <iostream>
    #include <string>
    #include <type_traits>
    #include <variant>
    #include <vector>
    #include <functional>
    
     using var_t = std::variant<std::function<void(void)>, std::function<void(int)>>;
    
    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
    
    int main() {
        std::vector<var_t> vec = {
            []() {std::cout << "void" << std::endl;},
            [](int arg) {std::cout << "int " << arg << std::endl;}
        };
    
        for (auto& v: vec) {
            std::visit(overloaded {
                [](const std::function<void(void)>& fv) { fv(); },
                [](const std::function<void(int)>& fi) { fi(42); }
            }, v);
        }
    }