Consider this. There is a class Derived
that inherits from some instantiation of a heavy templated class Base
, and there are many uses of Derived
in various source files. So it is reasonable to have only one Derived
-specific instantiation of Base
.
C++11 allows this via extern template
, but the problem here is that I want to type the Derived
-specific instantiation of Base
only once. Technically it is possible, as Derived
can hold an alias for that instantiation, but the question is: will it still force the compiler not to instantiate the template?
Here is the try:
// Base.hpp
template < typename Arg > struct Base { using TheArg = Arg; };
// Derived.hpp
#include "Base.hpp"
struct Derived : Base<int> { };
// The next line will be huge in real-world scenario, so I want to avoid it.
// extern template struct Base<int>;
// Instead I want this.
extern template struct Base<Derived::TheArg>;
// Derived.cpp
#include "Derived.hpp"
template struct Base<Derived::TheArg>;
// Use01.cpp
#include "Derived.hpp"
void use01() { Derived dd; }
The point here is to force Use01.cpp
not to instantiate Base<int>
and to refer to the explicit instantiation at Derived.cpp
instead.
I am compiling with gcc-v9.3
and the questions are:
extern template
declaration takes effect to all instantiations in the translation unit, or only to those which appear after its declaration?Derived::TheArg
instead of int
cause any problems with deferring the instantiation?Putting the extern template
declaration at the end of Use01.cpp
and commenting out the explicit instantiation at Derived.cpp
makes the compilation to fail, so this gives me some confidence that the extern template
declaration doesn't have to appear before any instantiation, so the second question still makes sense.
An explicit instantiation declaration of a specialization of a class template doesn’t prevent instantiating that specialization. After all, you still need to be able to refer to members of the resulting class, which means knowing everything about its layout. What it does do is prevent instantiation of its (non-inline) member functions, so that no code need be emitted for them.
Additionally, an explicit instantiation declaration must precede any source of implicit instantiation to be effective. If you want to name that specialization’s template argument just once, introduce a type alias for it before the explicit instantiation declaration and the definition of Derived
.