Suppose we have this header, with a function:
//template<int does_nothing=0> // <-- !! links correctly if uncommented
void incAndShow() {
static int myStaticVar = 0;
std::cout << ++myStaticVar << " " << std::endl;
}
If this is included in several .cpp
files, you'll get a linker error due to the redefinition of incAndShow()
.
Now, if you uncomment the //template<int does_nothing=0>
line above, this code will compile correctly with no linker error. And, the static variable will be shared correctly in all instances of incAndShow<0>()
.
This is because the C++ standard explicitly states that this should be allowed in its "One Definition Rule" (Page 43). The abbreviated text is:
There can be more than one definition of a... non-static function template (17.5.6)... provided that each definition appears in a different translation unit...
Now, note that the above is only true for templated functions, and not for non-templated functions. This is because, at least in the traditional paradigm, non-templated functions are compiled individually within each translation unit, and then the linker, envisioned as a totally separate process from the compiler, sees multiple definitions of the same symbol in different .obj
files and throws the error.
But somehow, this doesn't happen for templated functions.
So my question is: how, in a low-level sense, does this work?
- Does the compiler just compile each translation unit independently, meaning it generates multiple versions of the same symbol within each translation unit, but then have some special way to tell the linker to not worry about it?
- Does the compiler, on-the-fly, keep a note of the first time some templated function definition is seen in some translation unit, and automatically ignore upon seeing the same definition again when compiling the next translation unit?
- Does the compiler do some kind of "pre-compilation process," before compiling anything, where it goes through each file and removes duplicate templated code?
- Something else?
This has been brought up on StackOverflow a few times, but this is the first time I've seen anyone ask how the compilation process really happens on a low-level:
- Static variable inside template function (where my example came from)
- Why C++'s <vector> templated class doesn't break one definition rule?