astrophobia
astrophobia

Reputation: 889

recursion when packed variadic template has zero elements

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

Answers (2)

Saurav Sahu
Saurav Sahu

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

balki
balki

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

Related Questions