我正在寻找关于 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
最佳答案
第一件事是,如果任何翻译单元包含 header 并在编译器未看到声明的情况下导致特化定义,则您的代码违反了 ODR 规则。由于这是未定义的行为,一个编译器接受它而另一个编译器拒绝它的事实是合理的。
正确的代码,正如您已经知道的那样,是提供特化的声明,这将适用于任何编译器。
至于为什么它看起来有效,甚至为什么它在 gcc 中实际有效,这很可能是代码如何生成以及链接器如何处理目标文件的问题。特别是在 gcc 中,编译器将在需要它的翻译单元中生成专门化(并且看不到您自己的专门化),但它将被标记为 weak 符号。如果除 [至多] 一个定义之外的所有定义都是弱定义,则 gcc 链接器将接受多重定义的符号,而在最终可执行文件中留下强符号。
关于c++ - 模板特化,Windows 与 gcc 上的不同行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20478028/