How is template metaprogramming working here (static const int value = 1 + StarCounter<\U>::value;
) to print out 3
?
#include <iostream>
template <typename T>
struct StarCounter
{
static const int value = 0;
};
template <typename U>
struct StarCounter<U*>
{
static const int value = 1 + StarCounter<U>::value;
};
int main()
{
std::cout << StarCounter<int***>::value << std::endl;//How is it printing 3?
return 0;
}
Template metaprogramming (TMP) is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled.
You must use template metaprogramming to achieve what would have been easy and straightforward C++, and this always happens when the users of C++ aren't careful enough not to move too many things to compile-time.
Template meta-programming (TMP) refers to uses of the C++ template system to perform computation at compile-time within the code. It can, for the most part, be considered to be "programming with types" — in that, largely, the "values" that TMP works with are specific C++ types.
A template is a C++ programming feature that permits function and class operations with generic types, which allows functionality with different data types without rewriting entire code blocks for each type.
The first template creates a struct that will always return 0 when you call StarCounter<U>::value
.
The second template specialises the first one for cases where a pointer is used. So when you call it with StarCounter<U*>::value
, the second template is used, not the first and it will return StarCounter<U>::value + 1
. Note that it removes the pointer at each recursion step.
So the call to StarCounter<int***>::value
will expend to:
StarCounter<int***>::value // second template is used due to pointer
1 + StarCounter<int**>::value // second template is used due to pointer
1 + 1 + StarCounter<int*>::value // second template is used due to pointer
1 + 1 + 1 + StarCounter<int>::value // no pointer here, so first template is used
1 + 1 + 1 + 0
3
StarCounter<int>::value
equals 0
, because it's matched with first instantiation of the template, where value
is explicitly defined.
StarCounter<int*>::value = 1 + StarCounter<int>::value
equals 1
, because StarCounter<int*>
is matched with StarCounter<U*>
. Yes, StarCounter<T>
can also be considered as a match, but StarCounter<U*>
is more specific and that's why this one is preferred.
Similarly,
StarCounter<int**>::value = 1 + StarCounter<int*>::value
equals 2
and
StarCounter<int***>::value = 1 + StarCounter<int**>::value
equals 3
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With