Search code examples
c++templatesfunction-pointersvariadic-templatesfunction-definition

Deduce Function Arguments From A Function Type Declare, For Templated Struct Method?


I was wondering if it was possible to deduce the return type, and parameters from a function type define.

I was hoping to do something similar:

template<class T>
struct _function_wrapper_t
{
    [return of T] call([Args of T]....)
    {
        return (T)m_pfnFunc(Args);
    }

    void* m_pfnFunc;
};

int MultiplyTwoNumbers(int nNum, int nNum2)
{
    return nNum * nNum2;
}

int MultiplyThreeNumbers(int nNum, int nNum2, int* pnNum3)
{
    return nNum * nNum2 * *pnNum3;
}

int main()
{
    _function_wrapper_t<decltype(&MultiplyTwoNumbers)> two(&MultiplyTwoNumbers);
    _function_wrapper_t<decltype(&MultiplyThreeNumbers)> three(&MultiplyThreeNumbers);

    auto ret1 = two.call(1, 2);
    auto ret2 = three.call(4, 5, 8);

}

However I'm not sure if its possible to discern the return type and function arguments from a type of function pointer.

if you did say

typedef void*(__cdecl* fnOurFunc_t)(const char*, int, float**);

The compiler knows to use that as the type in the future, does the same apply further to templates? This is needed for a VERY specific use case.

Thanks in advance!


Solution

  • The simple solution is to let the compiler deduce return type and let the caller pass the right types (and fail to compile when they don't):

    template<class T>
    struct _function_wrapper_t
    {
        template <typename ...U>
        auto call(U&&... t)
        {
            return m_pfnFunc(std::forward<U>(t)...);
        }
    
        T m_pfnFunc;
    };
    

    If you do not like that you can use partial specialization:

    template<class T>
    struct _function_wrapper_t;
    
    template <typename R,typename...Args>
    struct _function_wrapper_t<R(*)(Args...)>
    {
        R call(Args...args)
        {
            return m_pfnFunc(args...);
        }
        using f_type = R(*)(Args...);
        f_type m_pfnFunc;
    };
    

    Live Demo

    PS: perfect forwarding is also possible in the latter case but it requires some boilerplate that I left out for the sake of brevity.