查看以下代码:
#include <vector>
template class std::vector<int>;
extern template class std::vector<int>;
int main() {}
虽然GCC 5.2可以正常编译,clang 3.6给出以下错误信息:
main.cpp:4:28: error: explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')
extern template class std::vector<int>
^
main.cpp:3:21: note: explicit instantiation definition is here
template class std::vector<int>
^
1 error generated.
对于下面的代码
template <typename T>
void f() {}
template void f<int>();
extern template void f<int>();
int main() {}
GCC和clang都出错了。GCC的消息是
main.cpp:5:29: error: duplicate explicit instantiation of 'void f() [with T = int]' [-fpermissive]
extern template void f<int>();
, clang是
main.cpp:5:22: error: explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')
extern template void f<int>();
^
main.cpp:4:15: note: explicit instantiation definition is here
template void f<int>();
^
1 error generated.
这两个家伙怎么了?标准是否禁止显式模板实例化声明之前有显式定义?这对我来说没什么意义。毕竟,先定义再声明又有什么害处呢?
From [temp.explicit]/11
如果一个实体是同一翻译单元中显式实例化声明和显式实例化定义的主题,则定义应遵循声明。
对于第一个例子,GCC也应该给出一个错误。
2008年的相关bug, GCC似乎在检测类的错误时出现了问题,以下内容也被遗漏了
template <typename T> class f {};
template class f<int>;
extern template class f<int>;
int main() {}