If anybody is curious about how templates work, there are many ways, but the two most historically popular are:
Prelinker:
1. Compile each file, noting which templates are needed in a section in the object file
2. Have a special program called the "prelinker" run before the linker that reads each .o file, and then somehow instantiates each template (which usually, but not always requires reparsing the C++ file)
Weak Symbols:
1. When compiling instantiate every needed template, but mark it somehow in the object file as being weak, so that the linker only pulls in one instantiation for each definition.
The prelinker used to be more popular, as if you e.g. instantiate the same template in every single file, your compiler does tons more work with the weak symbols approach, but now weak symbols are popular both because they are much simpler to implement and the fact that compilation is usually parallel, while linker is typically not means that walk clock times may even be faster.
Nobody, AFAIK. Even with an explicit "export template", it's basically impossible because of of the interaction of all the features of the C and C++ and CPP parts of the language.
(Precompiled headers are/were are thing, but they're very brittle. Of course, one assumes you already know this, I'm trying to provide additional exposition.)
People started to use templates for metaprogramming and from that point on the scope for "reuse" of templates isn't really there. (Reusing parsing might be plausible, but it's really difficult because parsing is extremely context-sensitive because of SFINAE, #defines, etc.)
Some might comment that "modules" is "export template" all over again, but this time there are actually 2-3 implementations of 2-3 of the proposals and everyone is confident that the remaining minor problems can be resolved satisfactorily... and they're all exchanging experiences to help each other!
"Precompiled headers are/were are thing, but they're very brittle."
In compilers other than Visual Studio, yes (or so I'm mostly told - I don't have all that much experience with them), but msvc has had them since at least VS6 (late 1990's) when I first started using them, and they work very well and have saved me many, many hours since then. Maybe once or twice I had to delete the pch file in all that time, and that was most likely more of a issue of the GUI mangling the saved internal state than the actual compiler.
I've heard pushback against precompiled headers from Unix land for 2 decades, I'm not really sure where it comes from. I have the impression it's mostly cognitive dissonance - 'msvc has it and gcc doesn't, therefore it must be bad because gcc is 'better' than msvc'. It's similar to #pragma once - in use, it's objectively better in every possible way than include guards are, and gcc fanboys still dismissed it back when gcc didn't have them.
FWIW, gcc has had pragma once for ages. On the other hand recently we had issues with MSVC not recognizing that an header and its simlink were the same. GCC and clang had no problems.
There is a reason pragma once is not standardized. Defining when to include lines refer to the same file is extremely hard.
Prelinkers are dying, but 20 years ago they were the normal way of doing things. 30 years ago, Cfront had to use them because it was relying on existing unix linkers that did not have weak symbol support.
I am still not sold on templates. They look like they might help the Google's and Microsoft's but for most code bases they seem to be forcing a dual system of dependencies without much benefit.
EDG's frontend used to be prelinker based. I would guess that it supports the weak symbols method now, since they were involved in developing the itanium abi:
Yep, and EDG was the only frontend to implement "export template" (and Comeau was the only backend to implement it, so far as I know). I think that's the only reason why they implemented it this way - outside of template export, there's no particular reason to do templates like that. The other technique, with folding duplicate sections in object files, is necessary for inline functions anyway, so might as well use it for templates...
That's backwards if my memory is correct. Borland compiled a copy of the template for each file[1] you compiled, but cfront tried to compile each template only once.
Cfront also basically never worked well.
1: the technical term is "compilation unit" since #include means you're never compiling just one file
Prelinker:
1. Compile each file, noting which templates are needed in a section in the object file
2. Have a special program called the "prelinker" run before the linker that reads each .o file, and then somehow instantiates each template (which usually, but not always requires reparsing the C++ file)
Weak Symbols:
1. When compiling instantiate every needed template, but mark it somehow in the object file as being weak, so that the linker only pulls in one instantiation for each definition.
The prelinker used to be more popular, as if you e.g. instantiate the same template in every single file, your compiler does tons more work with the weak symbols approach, but now weak symbols are popular both because they are much simpler to implement and the fact that compilation is usually parallel, while linker is typically not means that walk clock times may even be faster.