A static variable of a function is initialized only once when the function gets the control the first time.
So when the function specialization getID2<int> is called the first time
std::cout << getID2<int>() << std::endl;
its static variable id2 is initialized by the value of the static variable id of the non-template function by 0 (pay attention to that in the return statement of the non-template function there is used the post-increment operator
return id++;
So the returned value of the function is the value of the variable id before the increment.)
. So in the second call of the function template specialization
std::cout << getID2<int>() << std::endl;
the declaration
static int id2 = getID();
is skipped and the function again outputs 0.
The same is valid for the function template specialization getID2<double> but in this case in the first call of the function the value of id is already was changed to 1. So all calls of the specialization returns the initialized static variable id2 with the value 1.
std::cout << getID2<double>() << std::endl;
Again in subsequent calls of the specialization the declaration
static int id2 = getID();
is skipped because the static variable id2 was already initialized.
Pay attention to that specialization of a template function are different functions.
From the C++ 17 Standard (9.7 Declaration statement)
4 Dynamic initialization of a block-scope variable with static storage
duration (6.7.1) or thread storage duration (6.7.2) is performed the
first time control passes through its declaration; such a variable is
considered initialized upon the completion of its initialization....