shved
shved

Reputation: 406

Template: Determine template arguments by function prototype

I have the function pointer type or function prototype:

int function (int arg);
typedef int (*function_t) (int arg);

and template class like

template <typename T_ret, typename... T_args> 
class caller {
    T_ret (*m_p) (T_args... args);
public:
    T_ret call (T_args... args) {
        return m_p(args);
    }
    caller (T_ret (*p)(T_args...args)) : m_p(p) {}
};

Is it possible to make compiler automatically determine template parameters within code like

class caller2 : public caller <__something_with_function_prototype__> {
    caller2 : caller (function) {};
};

And similar question: is it possible to do this but with another template class instead of function?

template <typename T_ret, typename... T_args> class example;
typedef example<int, int> example_t;

Thank you.

Upvotes: 1

Views: 444

Answers (2)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48447

Not sure if this is what you want, but maybe:

#include <iostream>

int function (int arg) { return arg; }
typedef int (*function_t) (int arg);

template <typename T_ret, typename... T_args> 
class caller {
    T_ret (*m_p) (T_args... args);
public:
    T_ret call (T_args... args) {
        return m_p(args...);
    }
    caller (T_ret (*p)(T_args...args)) : m_p(p) {}
};

template <typename T_ret, typename... T_args>
caller<T_ret, T_args...> get_caller(T_ret(*prototype)(T_args...))
{
    return caller<T_ret, T_args...>(prototype);
}

int main()
{
    function_t f = &function;
    auto c = get_caller(f);
    std::cout << c.call(1) << std::endl;
    return 0;
}

Live demo link.

OR maybe:

#include <iostream>

int function (int arg) { return arg; }
typedef int (*function_t) (int arg);

template <typename T> 
class caller {};

template <typename T_ret, typename... T_args> 
class caller<T_ret(*)(T_args...)> {
    T_ret (*m_p) (T_args... args);
public:
    T_ret call (T_args... args) {
        return m_p(args...);
    }
    caller (T_ret (*p)(T_args...args)) : m_p(p) {}
};

int main()
{
    caller<decltype(&function)> c(&function);
    std::cout << c.call(1) << std::endl;
    return 0;
}

Yet another live demo link.

Upvotes: 1

Jarod42
Jarod42

Reputation: 217135

You may use some helper:

template <typename F> struct helper;

template <typename T_ret, typename... T_args>
struct helper<T_ret (*) (T_args... args)>
{
    using type = caller<T_ret, T_args...>;
};

And then use it like

int function (int arg);

class caller2 : public helper<decltype(&function)>::type {
public:
    caller2() : caller (&function) {}
};

And to be more generic:

template <typename T_ret, typename... T_args>
struct helper<T_ret (*) (T_args... args)>
{
    template <template <typename, typename...> class C>
    using type = C<T_ret, T_args...>;
};

And then

class caller2 : public helper<decltype(&function)>::type<caller> {
public:
    caller2() : caller (&function) {}
};

and so helper<decltype(&function)>::type<example> is example<int, int>

Upvotes: 1

Related Questions