C++ 访问并调用std::function的变体

C++ 访问并调用std::function的变体,c++,c++17,C++,C++17,我正在使用存储不同的s签名。所述函数存储在向量中,向量从地图中检索 如何调用向量中的每个函数?我觉得我应该用,但我想不出正确的用法 #include <variant> #include <functional> #include <map> #include <iostream> #include <functional> using var_t = std::variant<std::function<void(voi

我正在使用存储不同的s签名。所述函数存储在向量中,向量从地图中检索

如何调用向量中的每个函数?我觉得我应该用,但我想不出正确的用法

#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;
}
#包括
#包括
#包括
#包括
#包括
使用var_t=std::variant;
枚举类EventEnum{A,B,C};
结构控制器{
模板
无效认购(var_t fn){
auto&callbacksVec=callbacks.at(E);
回调向量推回(fn);
}
模板
作废通知(){
auto&callbacksVec=callbacks.at(E);
用于(自动和功能:callbacksVec){
//std::visit([](自动&参数){std::invoke(参数);},func);
}
}
std::map回调;
};
int main(){

auto fn=[](){std::cout
std::visit
要求变量中的每个类型都有一个有效的“action”。如果
func
要有一个
std::function
而不是像现在这样的
std::function
,那么就没有办法对它进行操作。因为这(可以)取决于运行时,
std::visit
必须在编译时检查变量的每一个可能的替代方案是否可以用于调用您的可调用变量

例如,您可以将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);
模板结构重载:Ts..{using Ts::operator()…;};
模板重载(Ts…)->重载;
标准::访问(超负荷){
[](const std::function&Void){std::invoke(Void);},
[](const std::function&Int){std::invoke(Int,1);}},func);

下面是另一个根据您的情况改编的示例:

#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);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用var_t=std::variant;
模板结构重载:Ts..{using Ts::operator()…;};
模板重载(Ts…)->重载;
int main(){
标准::向量向量向量={

[](){std::您是否尝试过根据这些示例编写visitor lambda:?您可以展示您的尝试吗?仅供参考,您遗漏了一些参考,即使它确实编译了,您也会修改本地副本,而不是
回调
。是的,因此我尝试了问题中注释的内容,我还尝试了复制链接中的“重载运算符()”示例没有成功。但公平地说,我仍在思考这个问题,我没有完全理解它。@Raket1111您能更具体一点吗?
auto-func
应该是
auto&func
,但variant“必须没有参考选项”@Fluffy我是说
callbacksVec
。(还有你提到的那个,虽然没有那么糟糕)对不起,除非我做错了,否则这似乎不起作用?电话模棱两可:好的,谢谢!我可以这样做;两个答案都是有效的,我选择这一个是为了努力,或者在godbolt上修复我的代码,额外的解释,因为你在时间上有些超前;D