Vector of std::function with different signatures

前端 未结 7 1769
离开以前
离开以前 2020-12-03 03:32

I have a number of callback functions with different signatures. Ideally, I would like to put these in a vector and call the appropriate one depending on certain conditions.

7条回答
  •  情话喂你
    2020-12-03 04:16

    Not sure how useful this would be for you, it is based on boost::any, redundant parameters are ignored. You can add try...catch for boost::bad_any_cast to prevent crash in case of mismatch between arguments' and parameters' types. Though I think regular std::bind is a better choice.

    DEMO

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    struct IGenericFunction
    {
        virtual ~IGenericFunction() = default;
    
        virtual void call(boost::any a1 = boost::any{}
                        , boost::any a2 = boost::any{}
                        , boost::any a3 = boost::any{}
                        , boost::any a4 = boost::any{}) = 0;
    };
    
    template 
    class GenericFunction : public IGenericFunction
    {
    public:
        GenericFunction(std::function f) : _f{ f } {}
    
        virtual void call(boost::any a1 = boost::any{}
                        , boost::any a2 = boost::any{}
                        , boost::any a3 = boost::any{}
                        , boost::any a4 = boost::any{}) override
        {
            call_func(std::make_tuple(a1, a2, a3, a4)
                    , std::make_index_sequence{});
        }
    
    private:            
        template 
        void call_func(Tuple t, std::index_sequence s)
        {
            _f(boost::any_cast<
                    typename std::tuple_element::type
               >(std::get(t))...);
        }
    
        std::function _f;
    
        using Params = std::tuple;
    };
    
    template 
    std::shared_ptr make_generic_function_ptr(void(*f)(Args...))
    {
        return std::make_shared>(f);
    }
    
    void func1(const std::string& value)
    {
        std::cout << "func1 " << value << std::endl;
    }
    
    void func2(const std::string& value, int min, int max)
    {
        std::cout << "func2 " << value << " " << min << " " << max << std::endl;
    }
    
    int main()
    {
        std::vector> functions;
    
        functions.push_back(make_generic_function_ptr(&func1));    
        functions.push_back(make_generic_function_ptr(&func2));
    
        for (auto f : functions)
        {
            f->call(std::string("abc"), 1, 2);
        }
    }
    

提交回复
热议问题