Is this a correct usage of extern template in C++11? (Can it be that the extern template class and respective template class is visible in the same translation unit?)
// example.hpp:
#pragma once
template< typename T >
class C {
void f(T);
};
// question is about the next two lines
extern template class C< float >;
extern template class C< double >;
// example_def.hpp:
#include "example.hpp"
template< typename T >
void C< T >::f(T) {
//... smth. practicable
}
// example.cpp:
#include "example_def.hpp"
template class C< float >;
template class C< double >;
// other.hpp:
#pragma once
void g();
// other.cpp:
#include "other.hpp"
#include "example.hpp"
// maybe those two lines should be here instead?
void g() {
C< float >();
C< double >();
}
// main.cpp:
#include "example.hpp"
#include "other.hpp"
// ...and here?
int main() {
C< float >();
C< double >();
g();
return 0;
}
Yes, both an
extern template classspecification (called explicit instantiation declaration by the Standard) and atemplate classspecification (called explicit instantiation definition by the Standard) can be in the same translation unit, if the definition (withoutextern) follows the declaration (withextern):(Emphasis mine). The terms explicit instantiation declaration and explicit instantiation definition are defined here:
The effect of these explicit instantiations is as follows:
The explicit instantiation declaration (with
extern) prevents all implicit instantiations to take effect (except for inline functions and class template specializations, §14.7.2/10).The explicit instantiation definition (without
extern) causes the instantiation to happen no matter what, i.e. it overrides the explicit instantiation declaration (this also follows from §14.7.2/10).General comments
The fact that your explicit instantiation declarations are located in the header file that defines the template implies that anyone who includes the header files in order to make use of the template will either have to also add an explicit instantiation definition, or, alternatively, needs to link to the code of another
.cppfile that includes such an explicit instantiation definition.This can be confusing and is probably not a very good idea when you expect many different users to instantiate the template for many different types. But it can be sensible if the number of instantiations for distinct types is small and you can anticipate them all. Of course you must make sure that there is one (or several)
.cppfile(s) that include explicit instantiation definitions for all the instantiations required, and that its corresponding object file is linked with the project at build time.