c++;建立一个函数名表,函数有不同的签名 我想知道,如果可以在C++中构建一个函数表的名称,比如“代码> map < /COD>”。但是

c++;建立一个函数名表,函数有不同的签名 我想知道,如果可以在C++中构建一个函数表的名称,比如“代码> map < /COD>”。但是,c++,function,c++11,c++17,C++,Function,C++11,C++17,这些函数具有不同的签名。我可以假设它们的返回类型与void相同 我在想定义一下 struct-ftable { std::字符串名; void(void*pfun)(;//这仅用于一个函数签名 }; 但是如何使它适用于不同类型的功能呢 我问了一个相关的问题。在这个问题中,我尝试将函数存储到某个容器中,但我意识到我不能使用占位符存储函数(请参见下面的代码)。C++可以这样做吗?谢谢 template <typename F, typename ... Args> std::functi

这些函数具有不同的签名。我可以假设它们的返回类型与
void
相同

  • 我在想定义一下

    struct-ftable
    {
    std::字符串名;
    void(void*pfun)(;//这仅用于一个函数签名
    };

  • 但是如何使它适用于不同类型的功能呢

    我问了一个相关的问题。在这个问题中,我尝试将函数存储到某个容器中,但我意识到我不能使用占位符存储函数(请参见下面的代码)。C++可以这样做吗?谢谢

    template <typename F, typename ... Args>
    std::function<void()> MapFun (F const & f, Args const & ... args)
        { return [=]{ f(args...); }; }
    
    void userFun1 (int i1, int i2)
    { std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
    
    int main ()
    {
       auto l1 = MapFun(userFun1, 1, 2);
       std::unordered_map<std::string, std::function<void()>> func_map;
       func_map["userFun1"] = std::bind(l1); // this is okay;
       //func_map["userFun1"] = std::bind(userFun1, std::placeholders::_1, std::placeholders::_2); // this is wrong;
       //auto lll1 = MapFun(userFun1, std::placeholders::_1,std::placeholders::_2); // also wrong.
    }
    
    模板
    std::函数MapFun(F常量和F,Args常量和…Args)
    {return[=]{f(args…;};};}
    void userFun1(inti1,inti2)
    
    {std::cout如果在创建
    std::function
    的对象时,您知道函数签名,那么您可以执行以下操作

    #include <iostream>
    #include <functional>
    #include <unordered_map>
    
    void userFun1 (int i1, int i2)
    { 
        std::cout << "uf1, " << i1 << ", " << i2 << std::endl; 
    }
    
    
    int main()
    {
        std::unordered_map<std::string, std::function<void()>> func_map;
        func_map["userFun1"] = std::bind(userFun1,1,2);
        func_map["userFun1"]();
        int i1{2},i2{3};
        func_map["userFun1.1"] = std::bind(userFun1,std::ref(i1),std::ref(i2));
        func_map["userFun1.1"]();
        i1 = 3;
        i2 = 4;
        func_map["userFun1.1"]();
        return 0;
    }
    
    #包括
    #包括
    #包括
    void userFun1(inti1,inti2)
    { 
    
    std::cout这是可能的,但在某个时候,您需要知道返回和参数类型

    您可以使用类型擦除类隐藏返回/参数类型,然后存储类型擦除类

    #include <iostream>
    #include <functional>
    #include <unordered_map>
    
    class MyLambda {    
    
        public:
    
            MyLambda() = default;
    
            virtual ~MyLambda() = default;
    
    };
    
    template <typename T>
    class HiddenLambda : public MyLambda {
        static_assert(std::integral_constant<T, false>::value, "Template parameter needs to be of function type.");
    };
    
    template <typename Ret, typename... Args>
    class HiddenLambda<Ret(Args...)> : public MyLambda {
    
            public:
    
                HiddenLambda(std::function<Ret(Args...)> _fun) :  fun_(_fun) { }
    
                Ret operator() (Args... args) {return fun_(args...);}
    
            private:
    
            std::function<Ret(Args...)> fun_;
    };
    
    int main() {
    
        std::unordered_map<std::string, std::shared_ptr<MyLambda>> my_lambdas;
    
        my_lambdas.insert(std::make_pair("fun1", std::shared_ptr<MyLambda>( 
            new HiddenLambda<size_t(std::string)>(
                [](std::string s) { return s.size(); } // <- lambda you want to store
                )
            )
        ));
    
        my_lambdas.insert(std::make_pair("fun2", std::shared_ptr<MyLambda>( 
            new HiddenLambda<int(int)>(
                [](int x) { return x * 5; } // <- lambda you want to store
                )
            )
        ));
    
        auto it = my_lambdas.find("fun1");
    
        /* Get the function we want! */
        std::shared_ptr<MyLambda> a_lam = it->second;
    
        /* Need to know the types to actually use it though */
        HiddenLambda<size_t(std::string)>& actual_lam = dynamic_cast<HiddenLambda<size_t(std::string)>&>(*a_lam);
    
        std::cout << actual_lam("how long is this string?") << "\n";
    }
    
    #包括
    #包括
    #包括
    类MyLambda{
    公众:
    MyLambda()=默认值;
    virtual~MyLambda()=默认值;
    };
    模板
    HiddenLambda类:公共MyLambda{
    静态_断言(std::integral_constant::value,“模板参数必须是函数类型”);
    };
    模板
    HiddenLambda类:公共MyLambda{
    公众:
    HiddenLambda(std::function _-fun):fun(_-fun){
    Ret运算符()(Args…Args){return(Args…;}
    私人:
    std::函数fun;
    };
    int main(){
    std::无序映射我的lambdas;
    我的lambdas.insert(std::make_pair(“fun1”),std::shared_ptr(
    新希登兰姆达酒店(
    
    [](std::string s){返回s.size();}你为什么认为你需要这个?听起来像是XY问题。你想解决的潜在问题是什么?在你从地图中检索函数后,你怎么知道它的签名是什么?@ RaymondChen,我想你是对的。C++是一种需要在编译时知道类型的语言。我已经更新了我的问题,“超级,谢谢你。”注释如果您在编译时知道签名(例如,“名为
    bob
    的项始终是
    void(*)(int,int)
    ”),那么您可以将普通函数指针转换为
    void(*)(
    )进行存储,然后将其转换为
    void(*)(int,int)
    检索后。不同签名的函数指针可以在不损失保真度的情况下相互转换,但在使用它们调用函数之前,必须转换回原始类型。如果转换到错误的签名,然后尝试调用函数,则结果未定义(即“坏”).static_assert
    仅涵盖视图数据类型(浮点类型如何?类/结构?)。更好:不要实现模板!谢谢你的回答。但是当从映射中获取函数句柄时,它仍然需要知道类型。它具有与使用
    std::vector
    相同的限制。我已经更新了我的问题,你有什么其他建议吗?@J.Yang你总是需要知道签名。在代码中的某个点你需要给函数提供参数,在那一点上你需要知道所有参数的类型。我已经添加了一个可以帮助的编辑。@ J.Yang.请让我知道如果你工作了,我很想知道你到底做了什么。你对这个答案很满意,请考虑接受它。@巴斯托感谢你的病人。。我需要考虑一下你的编辑V2。如果这不起作用,我想我会修复共享函数的签名。因此它将接受多个向量。如果我想发送几个int输入,我必须将它们全部放在一个向量中,并在函数开始时取出。谢谢你的回答。std::ref听起来很棘手。我有更新d我的问题,你认为这是一个解决办法吗?@J.Yang对于你的更新,我认为这是不可能的。对于任何插件系统,都有一套固定的函数调用或API,插件加载程序和插件本身都知道。在你的情况下,你可以创建你的客户端代码的包装器,知道客户端函数的签名和什么这些值需要传递给客户机函数,并从服务器代码中调用这个包装函数。希望这会有所帮助!
    /* include above classes and includes */
    void myfunc(int x, int y) {
        std::cout << "uf1, " << x << ", " << y << std::endl;
    }
    
    int main() {
        std::unordered_map<std::string, std::shared_ptr<MyLambda>> func_map;
    
        func_map["userFun1"] = std::shared_ptr<MyLambda>(
            new HiddenLambda<void(int, int)>( &myfunc ) // <- no args binded, notice the type = void(int,int)
        ); 
    
        func_map["userFun2"] = std::shared_ptr<MyLambda>( 
            new HiddenLambda<void(int)>( std::bind(myfunc, std::placeholders::_1,  5) ) // <- one args binded, notice the type = void(int)
        ); 
    
        func_map["userFun3"] = std::shared_ptr<MyLambda>(
          new HiddenLambda<void()>(  std::bind(myfunc, 1, 2))  // <- two args binded, notice the type = void()
         );
    
        /* we still need to know the type though,it will be either void(int, int), void(int) or void() */
        HiddenLambda<void(int)>& actual_lam = dynamic_cast<HiddenLambda<void(int)>&>(*func_map["userFun2"]);
    
        actual_lam(4);
    
    }
    
    enum Types { kVOID, kINT_INT }; // <- verbosely define all the possible ones you would use 
    
    std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
        return 
            {
              kVOID, /* <- some sensible default */
                std::shared_ptr<MyLambda>(
                   new HiddenLambda<void()>( []{} ) 
                )
            }; 
    }
    
    std::pair<Types, std::shared_ptr<MyLambda>> Factory(){
        return
         {
            kVOID_INT_INT,
            std::shared_ptr<MyLambda>(
            new HiddenLambda<void(int, int)>( [](int x, int y){ std::cout << (x + y);} ) 
            )
       };
    }
    
    int main() {
    
        std::unordered_map<std::string, std::pair<Types, std::shared_ptr<MyLambda>>> func_map;
    
        func_map.insert({"fun1", Factory()});
    
        auto it = func_map.find("fun1");
    
        /* always need to be able to deduce they type */
        if (it->second.first == kVOID) {
    
            CallHidden(*it->second.second); 
        } 
    
        else if (it->second.first == kINT_INT) { 
    
            CallHidden<int, int>(*it->second.second, 3, 4); 
    
        } else {
    
            /* other ones you have statically typed */
    
        } 
    }