2013-11-22 3 views
2

Я только начал изучать шаблоны на C++ и не знаю терминологию, но это то, что я хочу делать. Допустим, у меня есть три функции.C++ шаблоны это возможно?

double fa(double a) 
{ 
    return a; 
} 

double fb(double a, double b) 
{ 
    return (a+b); 
} 

double fc(double a, double b, double c) 
{ 
    return (a+b+c); 
} 

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

void compute(double (*func)(double)) 
{ 
    func(1); 
    std::cout << "1 argument here"; 
} 

void compute(double (*func)(double, double)) 
{ 
    func(1,2); 
    std::cout << "2 arguments here"; 
} 

void compute(double (*func)(double, double, double)) 
{ 
    func(1,2,3); 
    std::cout << "3 arguments here"; 
} 

Есть ли способ, чтобы определить функцию «вычислений» без перегрузки функций, но с использованием шаблонов вместо? Поэтому я мог бы передать функцию с произвольным числом аргументов.

+0

Вы всегда проходя 1,2,3 ... ? – chris

+0

Это не Haskell или OCaml, C++ на самом деле имеет функции с несколькими аргументами, а не currying. Так что это должно быть 'void compute (double (* func) (double, double, double))' –

+0

Ops, fixed. Да, допустим, всегда проходим 1,2,3 ... – Winten

ответ

2

Да, возможно, вы будете использовать шаблоны VARIADIC вывести как тип и количество аргументов, например:

template <typename... T> 
void compute(void (*func)(T...)) { 
    func(/* magic goes here (see below) */); 
    std::cout << sizeof...(T) << " arguments here\n"; 
} 

хитрый бизнес магия необходимо пройти по правому ряду аргументы. Это, безусловно, можно сделать, например, путем создания последовательности индексов. Другая деталь, оставшаяся вне кода выше, заключается в том, что T может изменяться произвольно. Если вы хотите заблокировать его только для последовательности double s, вы можете использовать подходящие типы объектов вместе с std::enable_if<cond, Type> или static_assert().

6

Ben (еще один Ben) уже предложил, что вам нужны вариативные шаблоны.

Вот функтор, который делает добавление по переменным числом аргументов:

struct { 
    double operator()(double first) const 
    { 
     return first; 
    } 

    double operator()(double first, double second) const 
    { 
     return first + second; 
    } 

    template<typename... T> 
    double operator()(double first, double second, T... t) const 
    { 
     return (*this)(first + second, t...); 
    } 
} variadic_add; 

А вы можете назвать это так:

template<typename Reducer> 
void compute(Reducer reduce) 
{ 
    reduce(1); 
    std::cout << "1 arguments here"; 
    reduce(1,2); 
    std::cout << "2 arguments here"; 
    reduce(1,2,3); 
    std::cout << "3 arguments here"; 
    reduce(1,2,3,4); 
    std::cout << "4 arguments here"; 
} 

compute(variadic_add); 
Смежные вопросы