The important things to note in this template definition are:
- the template parameters are values, and not types as many people usually expect in templates;
- the field
value
of the struct template is computed from these parameters;
- the template has a partial specialization for the second parameter
N
when set with 0
.
As you noticed, the template recurse on the value
field computation. that recursion would be infinite, if the partial specialization were not defined. When the second parameter "reaches" 0
, ie. when, by following the nesting of template instantiation in the attempt of getting the successive value fields necessary to compute the outermost one, the compiler finally needs to instantiate the template with parameter N equal to 0
, and selects the partial specialization version, which contains a constant value of 1
for the field. Then the compiler can compute each nested value field, to finally return to the outermost one.
Using this technique, it is possible to have the compiler compute certain values offline (ie. at compile time). This let the programmer have his constant values defined by their parameters and formula, rather than having to hardcode them, or make the compiled program compute them at each run.
But the issue with this approach, how clever it may seem, is its readability and thus ease of maintenance. That's most probably the reason why the new standard offers the constexpr
concept, which is a much proper way to define so called pure computation.
It should be noted that both fields of the templates are signed, and that the computation does not try to handle the negative values in any way. If N is initially set at -1
, the result could be interesting.