Вызов указателя функции шаблона с номером переменных аргумента

Я хочу написать функцию, которая вызывает другую функцию с ее аргументами. Посмотрите, как я хочу, чтобы он работал:

int sum(int a, int b) { return a + b }
int succ(int a)       { return a + 1 }
int size(char* str)   { return strlen(str) }

int call(???) { ??? }

int main() {
  cout << call(sum, 1, 2) << endl;
  cout << call(succ, 41) << endl;
  cout << call(size, "teste") << endl;
}

Ожидаемый результат:

3
42
5

Как я могу написать функцию call (считая, что возвращаемое значение всегда одно и то же)? Единственный способ, которым я могу думать, это следующее:

template<typename T> int call(T func, int a, int b) { return func(a, b) } 
template<typename T> int call(T func, int a)        { return func(a) } 
template<typename T> int call(T func, char* a)      { return func(a) } 

Есть ли способ решить это повторение с помощью шаблонов, va_list или что-нибудь еще?

Намерение:

Он предназначен для рисования геометрических изображений, разбора функции с параметрическим уравнением, которое нужно выделить. Пример:

Vector2i circle(float t, float radius) {
  return Vector2i(cos(t * 2*PI) * radius, sin(t * 2*PI) * radius);
}
// ...
draw(circle, 10);

Функция circle будет вызываться много раз внутри draw с разностями t (между 0.0 и 1.0). Остальные аргументы draw направляются непосредственно на функции, 10 будет radius. (Vector2i - это пользовательский класс).

Ответ 1

С++ 0x вариативные шаблоны:

template<typename Func, typename... Args>
auto call(Func func, Args&&... args)
-> typename std::result_of<Func(Args...)>::type
{
    return func(std::forward<Args>(args)...);
}

Ответ 2

Добавьте еще одну переменную шаблона:

template<typename T, typename U> 
int call(T func, U a) { return func(a) } 

template<typename T, typename U, typename V> 
int call(T func, U a, V b) { return func(a,b) }

Ответ 3

Как насчет простого #define для текущего решения на С++:

#define call(FUNC, ...) FUNC(__VA_ARGS__)

Вот демо. Я бы посоветовал использовать более лучшее имя, а затем общее имя типа call, поскольку вы используете #define.