模板专业化,不同的行为在Windows VS GCC? [英] template specialization, different behavior on windows vs gcc?

查看:110
本文介绍了模板专业化,不同的行为在Windows VS GCC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找关于GCC与具有专业化模板类的编译+链接不同于MSVC的概述或描述。例如,这种类型的东西适用于GCC而不是MSVC:

  // Base.h 
模板< typename T> struct Base {
template< class G> QString makeTitle(const G * obj){obj-> CompilerError();}
};

//在Foo.cpp
模板中<>模板< class G> QString Base< T_1> :: makeTitle(const G * obj){return mystr(); }
void SomeFunc(){
std :: cout<< Base< T_1>()。makeTitle< myclass>();
}

并且解决方案往往是我必须在Base.h中声明特化在使用它之前,或者在窗口上有链接错误。 MSVC如何/为什么以不同方式隐式实例化,以及为什么GCC对某些cpp文件中声明的特化有鲁棒性?

相关的问题提示一般的'使用前声明'要求: Template specialization - MSVC和GCC / MinGW之间的不同行为

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



正确的代码,正如您已经想到的那样,声明的专业化,这将在任何编译器工作。

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


I'm looking for an overview or description of what GCC does differently than MSVC for compile + link of template classes with specializations. For example, this type of thing works on GCC but not 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>() ;
}

and the solution tends to be that I must declare the specialization in Base.h before using it, or on windows there is a link error. How/why does MSVC implicitly instantiate differently, and how/why is GCC robust to the specialization being declared in some cpp file?

related question that notes the general 'declare before using' requirement: Template specialization - different behaviour between MSVC and GCC/MinGW

解决方案

The first thing is that your code is in violation of the ODR rule if any translation unit includes the header and causes the definition of the specialization without the compiler seeing a declaration. Since that is undefined behavior the fact that one compiler accepts it and the other rejects it is well within reason.

The correct code, as you already figured out is to provide the declaration of the specialization, and that will work in any compiler.

As of why it seems to work or even why does it actually work in gcc, this is most probably a matter of how the code is generated and the linker processes the object files. In particular in gcc the compiler will generate the specialization in the translation unit that needs it (and does not see your own specialization), but it will be marked as a weak symbol. The gcc linker will accept a symbol being multiply defined if all but [at most] one definitions are weak, leaving the strong symbol in the final executable.

这篇关于模板专业化,不同的行为在Windows VS GCC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆