Template factorial function without template specialization

The problem is that f<N>() always instantiates f<N-1>() whether that if branch is taken or not. Unless properly terminated, that would create infinite recursion at compile time (i.e. it would attempt instantiating F<0>, then f<-1>, then f<-2> and so on). Obviously you should terminate that recursion somehow.

Apart from constexpr solution and specialization suggested by NathanOliver, you may terminate the recursion explicitly:

template <int N>
inline int f()
{
    if (N <= 1)
        return 1;
    return N * f<(N <= 1) ? N : N - 1>();
}

Mind, this solution is rather poor (the same terminal condition must be repeated twice), I'm writing this answer merely to show that there are always more ways to solve the problem :- )


The issue here is that your if statement is a run time construct. When you have

int f() {
  if (N == 1) return 1; // we exit the recursion at 1 instead of 0
  return N*f<N-1>();
}

the f<N-1> is instantiated as it may be called. Even though the if condition will stop it from calling f<0>, the compiler still has to instantiate it since it is part of the function. That means it instantiates f<4>, which instantiates f<3>, which instantiates f<2>, and on and on it will go forever.

The Pre C++17 way to stop this is to use a specialization for 0 which breaks that chain. Starting in C++17 with constexpr if, this is no longer needed. Using

int f() {
  if constexpr (N == 1) return 1; // we exit the recursion at 1 instead of 0
  else return N*f<N-1>();
}

guarantees that return N*f<N-1>(); won't even exist in the 1 case, so you don't keep going down the instantiation rabbit hole.