Search code examples
c++templateslambdastd-function

How to manage various types of functions as containers


I am trying to manage function list through c++ template.

template<typename T, typename... Args>
std::map<std::wstring, std::function<T(Args...)>> mFuncs;

Above code is not the correct sentence, but like above code concept, I want to manage various types of functions as a List.

void RegisterFuncs()
{
   mFuncs.emplace(L"Func1", [&]()->bool{ ... });
   mFuncs.emplace(L"Func2", [&](int a, std::string b)->int{ ... });
   mFuncs.emplace(L"Func3", [&](std::tuple<int,int>& a){ ... });
   ...
   ...
   ...
   mFuncs.emplace(L"Func", [&](args...)->auto{ ... });
}
template<typename... TArgs>
inline auto CallFunc(const wchar_t* pKey, TArgs&&... pArgs)
{
   ...
   ...

   return mFuncs[pKey](std::forward<TArgs>(pArgs)...);
}

How can I implement the above concept?


Solution

  • use std::any

    std::map<std::string, std::any> f;
    int i = 3;
    
    void RegisterFuncs()
    {
        f.emplace("func1", std::function<double(int)>([&](int k){i = k; return 5.0; }));
        f.emplace("func2", std::function<bool()>([](){return false; }));
        //                      ^^^^^^^^^^^^^^^^ cant use lambda type becuase any_cast doesnt support implicit casting
    }
    
    template<typename R, typename... Args>
    inline R CallFunc(const std::string& name, Args&&... args)
    {
        return std::any_cast<std::function<R(Args...)>>(f[name])(args...);
    }
    
    int main()
    {
        RegisterFuncs();
    
        double r = CallFunc<double, int>("func1", 6);
        std::cout << "r: " << r << " i: " << i << "\n";
    
        bool b = CallFunc<bool>("func2");
        std::cout << std::boolalpha << "b: " << b << "\n";
    
        //types must match exactly or bad_any_cast is thrown
        try
        {
            int c = CallFunc<int>("func2");
            std::cout << "c: " << c << "\n";
        }
        catch(std::bad_any_cast e)
        {
            std::cout << e.what();
        }
    }