模板专用化,windows与gcc上的不同行为

template specialization, different behavior on windows vs gcc?

本文关键字:gcc 专用 windows      更新时间:2023-10-16

我正在寻找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文件中声明的专业化具有鲁棒性?

注意到一般"使用前声明"要求的相关问题:模板专业化-MSVC和GCC/MinGW 之间的不同行为

第一件事是,如果任何翻译单元包含头并导致在编译器没有看到声明的情况下定义专用化,那么您的代码就违反了ODR规则。由于这是未定义的行为,所以一个编译器接受它而另一个编译器拒绝它的事实是合理的。

正如您已经理解的那样,正确的代码是提供专门化的声明,这将在任何编译器中工作。

至于为什么它看起来有效,甚至为什么它在gcc中实际有效,这很可能是代码如何生成和链接器如何处理对象文件的问题。特别是在gcc中,编译器将在需要它的翻译单元中生成专门化(并且看不到您自己的专门化),但它将被标记为符号。如果除[最多]一个定义外的所有定义都是弱的,则gcc链接器将接受一个被多重定义的符号,并在最终可执行文件中保留强符号。