Reputation: 55
I'm trying to make a sum function using variadic template.
#include <iostream>
int sum() {
return 0;
}
template <int first, int ...Rest>
int sum() {
return first + sum<Rest...>();
}
int main() {
sum<1, 2, 3>();
}
But I got an error like this:
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...>();
so I changed
int sum { return 0; }
to
template<int first>
int sum { return first; }
but I got an another error:
test.cc:11:31: error: call of overloaded 'sum<3>()' is ambiguous
return first + sum<Rest...>();
~~~~~~~~~~~~^~
What should I do?
Upvotes: 0
Views: 54
Reputation: 180500
Your issue here is that sum<Rest...>()
when Rest
is empty won't call int sum()
because that function is not a template.
When you change it to
template<int first>
int sum { return first; }
then the issue becomes that template<int first> int sum
and template <int first, int ...Rest> int sum()
with Rest
being empty resolve to being the same function. There are no rules about a tie break here so you get a compiler error.
The old way to fix this was to just add another template parameter to the variadic template giving you an overload set of
template <int first>
int sum() {
return 0;
}
template <int first, int second, int ...Rest>
int sum() {
return first + sum<second, Rest...>();
}
and with that once Rest
is empty the only viable function to call is template <int first> int sum()
Now that we have fold expressions this isn't needed anymore and you can just use
template <int... Vals>
int sum() {
static_assert(sizeof...(Vals) > 0, "You must provide at least one template parameter");
return (... + Vals);
}
Upvotes: 4
Reputation: 217235
In C++17, you might do:
template <int first, int ...Rest>
int sum() {
return (first + ... + Rest);
}
Alternative would be to use class and specialization:
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; }
};
Upvotes: 3