Note that the syntax is slightly different. When you declare the main template:
template <unsigned...> struct sum;
Template parameters are not set after sum
. This is because you create a completely new pattern and declare that it accepts an arbitrary number of unsigned integers as parameters.
When you do this:
template<unsigned size, unsigned... sizes> struct sum<size, sizes...> { enum { value = size + sum<sizes...>::value }; };
You specialize in the template you previously announced. You say that when your parameters consist of an unsigned value followed by an arbitrary number of other unsigned values, use this definition. This is not exactly the same as the main template. The main template includes the possibility of having zero parameters.
When trying to do this:
template<unsigned size> struct sum { enum { value = size }; }; template<unsigned size, unsigned... sizes> struct sum // OOPS! A template called `sum` has already been declared! { enum { value = size + sum<sizes...>::value }; };
you are trying to create two different class templates with the same name that is not allowed.
Note that this is slightly different from how function templates work. With function templates, you can overload, so having multiple function templates with the same name is OK. However, with function templates, you cannot perform partial specialization, as this would create more ambiguity.
You might think that there is ambiguity between the main template and the specializations, but more specialized specializations always take precedence over less specialized specializations, and the primary template can always be considered the least specialized. If this is not the case, then partial specialization will not work at all.
source share