I was reading the responses to "Printing 1 to 1000 without loop or conditionals" and I am wondering why it is necessary to have the special case for NumberGeneration<1> in the top answer.
If I remove that and add a check for N == 1 in the template (code below), the code fails compilation with "template instantiation depth exceeds maximum" but I'm not sure why. Are conditionals handled differently in compile-time?
#include <iostream>
template<int N>
struct NumberGeneration
{
static void out(std::ostream& os)
{
if (N == 1)
{
os << 1 << std::endl;
}
else
{
NumberGeneration<N-1>::out(os);
os << N << std::endl;
}
}
};
int main()
{
NumberGeneration<1000>::out(std::cout);
}
Code generation and compilation doesn't branch depending on conditionals! Consider this:
// don't declare bar()!
void foo()
{
if (false) { bar(); }
}
If you never declare bar()
, this is a compilation error even though the inner scope can never be reached. For the same reason, NumberGeneration<N-1>
is always instantiated, no matter whether that branch can be reached or not, and you have infinite recursion.
Indeed, the static analogue of conditionals is precisely template specialization:
template <> struct NumberGeneration<0> { /* no more recursion here */ };
The conditional if
will not be handled at compile time. It will be handled at runtime.
Thus, even for N=1, the compiler will generate NumberGenerator<0>, then NumberGenerator<-1> ... endlessly, until reaching template instantiation depth.
Templates are instantiated at compile time, the template special case prevents the compiler from recursing below 1 when compiling.
if-clauses are evaluated at runtime, so the compiler has already failed at compiling your code when it would have any effect.
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