Reputation: 889
I have a class like this:
template<std::size_t T, std::size_t... Args>
class A{
public:
std::array<int,summation<Args...>::value> x;
}
where summation
is defined as:
template<std::size_t size, std::size_t... sizes>
struct summation
{
static const std::size_t value = size + summation<sizes...>::value;
};
template<std::size_t size>
struct summation<size>
{
static const std::size_t value = size;
};
The problem is that when Args is empty (i.e., I only specify the T
template) the base case does not work and I get a compilation error message:
error: wrong number of template arguments (0, should be 1 or more)
How can I modify the recursion of summation
to also properly handle the case when sizeof...(Args)==0
and return a value of 0 for the summation in this case? I am using C++11. Thanks
NOTE: I would also like this to work in a multithreaded environment, where summation can be simultaneously invoked by different threads with different parameters. What changes would be needed for this to work in a multithreaded environment? Thanks
Upvotes: 0
Views: 76
Reputation: 13934
This code:
size + summation<sizes...>::value;
translates
summation<1,2,3,4>::value
into
1 + summation<2, 3, 4>::value; // Trims out first parameter; matches variadic version
2 + summation<3, 4>::value; // Again, trims out first parameter;matches variadic version
3 + summation<4>::value; // Matches <size> version. You support signature up-to this point
4 + summation<>::value; // summation<> definition is missing in your code!!
More detailed explanation here. https://stackoverflow.com/a/48003232/1465553
Upvotes: 1
Reputation: 27664
The declaration should be the most generic one and then you can partially specialize with possible cases. Below solution works: https://godbolt.org/z/Ye7xEJ
template<std::size_t... sizes>
struct summation;
template<std::size_t size, std::size_t... sizes>
struct summation<size, sizes...>
{
static const std::size_t value = size + summation<sizes...>::value;
};
template<>
struct summation<> {
static const std::size_t value = 0;
};
std::size_t foo() {
return summation<1,3,4>::value;
}
std::size_t foo2() {
return summation<>::value;
}
Upvotes: 4