The original question has been refined.
Given a source code file named main.cpp
as follows:
#include <string>
extern template class std::basic_string<char>;
template<typename T>
struct A
{
T n = {};
T get() const
{
return n;
}
};
extern template struct A<int>;
int main()
{
auto a = A<int>{}.get(); // undefined reference to `A<int>::get() const'
auto b = static_cast<int>(std::string{}.size()); // ok
return a b;
}
What I expected:
Note that the source code has extern template class std::basic_string<char>
but no template class std::basic_string<char>
.
So, the compiler would not instantiate class std::basic_string<char>
, then g main.cpp
would cause link errors on line std::string{}.size()
as on line A<int>{}.get()
.
What I observed:
It is ok to g main.cpp
on line std::string{}.size()
. Online demo
Why does extern template class
technique not work as expected?
CodePudding user response:
There are at least two reasons why it doesn't work.
One There is no prohibition against library class and function template instantiations being declared as extern template
by the implementation. gcc
and libstdc
do just that.
$ g -E main.cpp | grep 'extern.*string'
extern template class basic_string<char>; // <-- from the library
extern template class basic_string<wchar_t>; // <-- from the library
extern template class std::basic_string<char>; // <-- your line
The standard library implementation contains the explicit instantiation definitions (you can dig the source).
Two An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required [temp.explicit].
A possible rationale for the NDR is that extern template
should not prevent inlining and other uses that do not involve linking. Indeed, with -O2
A::get
is inlined, and the program builds just fine. There is no established technology that would force this program to be rejected no matter what. It can be rejected because of linker errors, but there is no requirement for linker errors to appear.