我正在寻找GCC与MSVC不同的概述或描述,用于编译+链接具有特化的模板类。例如,这种类型的东西适用于GCC但不适用于MSVC:
// Base.h
template <typename T> struct Base {
template <class G> QString makeTitle(const G* obj){obj->CompilerError();}
};
// in Foo.cpp
template <> template <class G> QString Base<T_1>::makeTitle(const G* obj) { return mystr(); }
void SomeFunc() {
std::cout<< Base<T_1>().makeTitle<myclass>() ;
}
并且解决方案往往是我必须在使用它之前声明Base.h中的特化,或者在Windows上存在链接错误。 MSVC如何/为什么隐式地实例化,以及GCC如何/为什么对某些cpp文件中声明的特化是健壮的?
相关问题,注意到一般'使用前声明'要求:Template specialization - different behaviour between MSVC and GCC/MinGW
答案 0 :(得分:5)
第一件事是,如果任何翻译单元包含标题并导致特化定义而编译器没有看到声明,则代码违反ODR规则。由于这是未定义的行为,因此一个编译器接受它并且另一个拒绝它的事实在合理范围内。
正如您已经想到的那样,正确的代码是提供特化的声明,并且可以在任何编译器中使用。
为什么它似乎工作,甚至为什么它实际上在gcc中工作,这很可能是代码生成方式和链接器处理目标文件的问题。特别是在gcc中,编译器将在需要它的转换单元中生成特化(并且看不到您自己的特化),但它将被标记为弱符号。如果除了[最多]一个定义之外的所有定义都很弱,gcc链接器将接受一个被多重定义的符号,在最终的可执行文件中留下强符号。