Understand how to calculate the amount at compile time

I have this piece of code and you want to understand:

template <unsigned...> struct sum; template<unsigned size> struct sum<size> { enum {value = size}; }; template<unsigned size, unsigned... sizes> struct sum<size, sizes...> { enum { value = size + sum<sizes...>::value }; }; int _tmain(int argc, _TCHAR* argv[]) { sum<1, 2>::value; return 0; } 

I don’t understand why the unrealized amount (which accepts unsigned ... as the last specification of the structure, is there no conflict?) Should be present at all and how can the amount be specialized using the same parameters from the template part ( eg sum<size, sizes...> same as template <unsigned size, sizes...> . Why does the roar just not work?

 template<unsigned size> struct sum { enum {value = size}; }; template<unsigned size, unsigned... sizes> struct sum { enum { value = size + sum<sizes...>::value; }; }; 
+4
source share
2 answers

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.

+7
source

First announcement:

 template<unsigned int... Ns> struct sum; 

is a direct declaration: it declares a template as a template with a variable number of unsigned int parameters.

The first specialization is the basic case of a metafound, which contains the case when the package variable has only one parameter:

 template<unsigned size> struct sum<size> { enum {value = size}; }; 

The second specialization is a recursive case: it contains the case when the package variable has at least one parameter:

 template<unsigned size, unsigned... sizes> struct sum<size, sizes...> { enum { value = size + sum<sizes...>::value }; }; 

I suggest you learn more about the mechanisms of C ++ templates (for example, creating templates, specializing in templates, etc.) before writing / learning meta-programming.

0
source

Source: https://habr.com/ru/post/1501095/


All Articles