Значение в качестве аргументов для шаблона variadi c - PullRequest
0 голосов
/ 11 марта 2020

Я пытаюсь создать функцию суммирования, используя шаблон c.

#include <iostream>

int sum() {
   return 0;
}

template <int first, int ...Rest>
int sum() {
   return first + sum<Rest...>();
}

int main() {
   sum<1, 2, 3>();
}

Но я получил такую ​​ошибку:

test.cc: In instantiation of 'int sum() [with int first = 3; int ...Rest = {}]':  
test.cc:10:31:   recursively required from 'int sum() [with int first = 2; int ...Rest = {3}]'
test.cc:10:31:   required from 'int sum() [with int first = 1; int ...Rest = {2, 3}]'
test.cc:14:17:   required from here
test.cc:10:31: error: no matching function for call to 'sum<>()'
    return first + sum<Rest...>();
                   ~~~~~~~~~~~~^~
test.cc:9:5: note: candidate: 'template<int first, int ...Rest> int sum()'        
 int sum() {
     ^~~
test.cc:9:5: note:   template argument deduction/substitution failed:
test.cc:10:31: note:   couldn't deduce template parameter 'first'
    return first + sum<Rest...>();

, поэтому я изменил

int sum { return 0; } 

до

template<int first>
int sum { return first; }

но я получил еще одну ошибку:

test.cc:11:31: error: call of overloaded 'sum<3>()' is ambiguous
    return first + sum<Rest...>();
                   ~~~~~~~~~~~~^~

Что мне делать?

Ответы [ 2 ]

4 голосов
/ 11 марта 2020

Ваша проблема здесь в том, что sum<Rest...>(), когда Rest пусто, не будет вызывать int sum(), потому что эта функция не является шаблоном.

Когда вы изменяете ее на

template<int first>
int sum { return first; }

, тогда возникает проблема, что template<int first> int sum и template <int first, int ...Rest> int sum() с Rest пустым разрешением являются одной и той же функцией. Здесь нет правил о ie break, поэтому вы получите ошибку компилятора.

Старый способ исправить это состоял в том, чтобы просто добавить еще один параметр шаблона в шаблон variadi c, предоставив вам набор перегрузки

template <int first>
int sum() {
   return 0;
}

template <int first, int second, int ...Rest>
int sum() {
   return first + sum<second, Rest...>();
}

и с этим один раз Rest пуст единственная жизнеспособная функция для вызова - template <int first> int sum()

Теперь, когда у нас есть выражения сгиба, это больше не нужно, и вы можете просто использовать

template <int... Vals>
int sum() {
   static_assert(sizeof...(Vals) > 0, "You must provide at least one template parameter");
   return (... + Vals);
}
3 голосов
/ 11 марта 2020

В C ++ 17 вы можете сделать:

template <int first, int ...Rest>
int sum() {
   return (first + ... + Rest);
}

Альтернативой может быть использование класса и специализации:

template <int N, int Is...>
struct sum
{
    int operator () () const { return N + sum<Is...>{}(); }
};

template <int N>
struct sum<N>
{
    int operator () () const { return N; }
};
...