c++ - 模板特化,Windows 与 gcc 上的不同行为?

标签 c++ templates gcc linker

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

相关文章:

c - 为什么当你用字符串初始化一个没有 const 的数组时 gcc 不给出警告?

c++ - 为什么 C++ Builder 找不到我的 header ?

c++ - 关于 GLM 网格中的碰撞检测

c++ - 如何使用模板类的子类推导C++中模板函数的模板参数?

c++ - CRTP 类示例

c - 了解 C 中的缓冲

android - 从 QT/C++ 项目访问 Android Calendar Provider

c++ - Ubuntu 10.10下运行OpenGL项目报错

c++ - 多个容器和数据类型的模板函数

gcc 编译 SDL 的正确命令行参数