#include <iostream>
int function(int arg) { return arg; }
void function2() { std::cout << "void" << std::endl; }
template <typename T> class example;
template <typename T_ret, typename... T_arg>
class example <T_ret (*) (T_arg...)> {
public:
using type_f = T_ret (*) (T_arg...);
};
template <typename T>
class caller {};
// for non-void:
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) {}
};
// for void:
template <typename... T_args>
class caller<void(T_args...)> {
void (*m_p) (T_args... args);
public:
void call (T_args... args) {
return m_p(args...);
}
caller (void (*p)(T_args...args)) : m_p(p) {}
};
typedef int (*function_int_t) (int arg);
typedef void (*function_void_t) ();
typedef example <function_int_t> example_int_t;
typedef example <function_void_t> example_void_t;
int main()
{
caller<function_int_t> c1(&function);
caller<function_void_t> c2(&function2);
caller<example_int_t::type_f> c3(&function);
caller<example_void_t::type_f> c4(&function2);
std::cout << c1.call(1) << std::endl;
c2.call();
std::cout << c3.call(2) << std::endl;
c4.call();
return 0;
}