It works conceptually almost the same way as runtime recursion. f1<1000> calls f1<999> and then prints out 1000. f1<999> calls f1<998> and then prints out 999, etc. Once it gets to 1 the template specialization acts as the base case to abort the recursion.