原来的问题已经完善
给定一个名为main.cpp
的源代码文件如下:
#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;
}
我所期望的:
请注意,源代码具有extern template class std::basic_string<char>
,但没有template class std::basic_string<char>
。
因此,编译器不会实例化类std::basic_string<char>
,那么g++ main.cpp
会像在A<int>{}.get()
上一样在std::string{}.size()
上导致链接错误。
我观察到的情况:
到std::string{}.size()
线上的g++ main.cpp
是可以的。在线演示
为什么extern template class
技术不能按预期工作
它不起作用的原因至少有两个。
One不禁止实现将库类和函数模板实例化声明为extern template
。CCD_ 12和CCD_。
$ 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
标准库实现包含显式实例化定义(您可以挖掘源代码(。
Two一个实体是显式实例化声明的主体,并且它的使用方式也会导致翻译单元中的隐式实例化,它应该是程序中某个地方的显式实例化定义的主体;否则程序格式错误,不需要诊断
NDR的一个可能的理由是extern template
不应该阻止内联和其他不涉及链接的使用。事实上,使用-O2
,A::get
是内联的,并且程序构建得很好。没有任何既定的技术会迫使这个项目无论如何都被拒绝。由于链接器错误,它可以被拒绝,但不要求出现链接器错误。