I've seen some discussion of how templates were historically implemented in CFront around the web, including here.
The link describes the Borland model, which is familiar, and the CFront model with a separate template repository that persists between runs of the compiler. I can't think of any compilers now that are stateful in their normal mode of operation, only wrappers around compilers like
ccache and a few build systems that cache or support caching binary artifacts.
I'm mostly curious what the CFront template support was like and how it supported (or didn't support) incremental recompilation. If I changed a template in my project slightly and recompiled, how did CFront make sure that its template repository was brought to a consistent state? Was it necessary to periodically purge the template repository in order to get a "clean" build?
First the Borland Model, which sounds like what we use today for C++. Templates are parsed and processed in every translation unit. If the expanded template ultimately produces any object code, it emits weak symbols. When linking occurs, the linker will keep exactly one of the (identical (hopefully)) implementations associated with the weak symbol and drop the rest. The below passage shows that in order to support the Borland C++ toolchain or workalikes required a different linker. The fact that the Borland Model needs a new linker is elaborated on in the second paragraph.
Borland C++ solved the template instantiation problem by adding the code equivalent of common blocks to their linker; template instances are emitted in each translation unit that uses them, and they are collapsed together at run time. The advantage of this model is that the linker only has to consider the object files themselves; there is no external complexity to worry about. This disadvantage is that compilation time is increased because the template code is being compiled repeatedly. Code written for this model tends to include definitions of all member templates in the header file, since they must be seen to be compiled.
And the CFront Model. I'm assuming this would be a directory like
~/.templates that's managed by the compiler and stores expanded templates somehow. However, the comment about difficulties associated with building stuff in multiple directories or building multiple things in the same directory suggests that CFront created a template repository directory wherever it was launched and made no particular effort to avoid trampling the directory on future runs.
The AT&T C++ translator, Cfront, solved the template instantiation problem by creating the notion of a template repository, an automatically maintained place where template instances are stored. As individual object files are built, notes are placed in the repository to record where templates and potential type arguments were seen so that the subsequent instantiation step knows where to find them. At link time, any needed instances are generated and linked in. The advantages of this model are more optimal compilation speed and the ability to use the system linker; to implement the Borland model a compiler vendor also needs to replace the linker. The disadvantages are vastly increased complexity, and thus potential for error; theoretically, this should be just as transparent, but in practice it has been very difficult to build multiple programs in one directory and one program in multiple directories using Cfront. Code written for this model tends to separate definitions of non-inline member templates into a separate file, which is magically found by the link preprocessor when a template needs to be instantiated.