См. следующий код:
#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.
Что происходит с двумя парнями? Запрещает ли стандарт явному объявлению создания экземпляра шаблона предшествовать явному определению? Это не имеет большого смысла для меня. В конце концов, какой вред может быть в том, чтобы сначала определить, а затем объявить? Просто подумайте о случае с нешаблонными функциями.