模板专业化,Windows 与 gcc 上的不同行为?

Posted

技术标签:

【中文标题】模板专业化,Windows 与 gcc 上的不同行为?【英文标题】:template specialization, different behavior on windows vs gcc? 【发布时间】:2013-12-09 18:35:32 【问题描述】:

我正在寻找关于 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

【问题讨论】:

【参考方案1】:

首先,如果任何翻译单元包含标头并导致专门化定义而编译器没有看到声明,则您的代码违反了 ODR 规则。由于这是未定义的行为,一个编译器接受它而另一个编译器拒绝它的事实完全在合理范围内。

如您所见,正确的代码是提供专业化的声明,这适用于任何编译器。

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

【讨论】:

啊,“弱符号”,谢谢。这个讨论很有用:***.com/questions/2290587/… 如果默认定义有语法错误,它怎么会“看起来有效”?也许 MSVC 不检查 @peterkarasev:这对我来说并不明显。如果是这种情况,它不应该编译(它将无法生成 weak 风格)。虽然没有真正的代码以及它是如何编译的,但无法回答。

以上是关于模板专业化,Windows 与 gcc 上的不同行为?的主要内容,如果未能解决你的问题,请参考以下文章

ListView 中的不同行布局

如何计算两个多对多字段上的不同行

如何在不同列上的名字和姓氏的不同行上搜索多个名称?

gcc 的 C++ 部分模板专业化问题

使用t的不同行数在多个矩阵上的学生t检验(已配对)

为啥接受数组的 C++ 模板并不比接受 GCC 5.3 和 Clang 4.0 的指针更专业?