简体   繁体   English

使用g ++编译时静态函数的模板特化

[英]Template specialization for static function when compiling with g++

Why does the following code not work when compiling with: 为什么以下代码在编译时不起作用:

$ g++ temp_main.cpp temp_spec.cpp
/tmp/ccirjc3Y.o:temp_spec.cpp:(.text+0x100): multiple definition of `my::say()'
/tmp/ccSo7IVO.o:temp_main.cpp:(.text$_ZN2myILi0EE3sayEv[my::say()]+0x0):
first defined here collect2: ld returned 1 exit status

I'm trying to have specialization of static function only when using paramteter 0. 我正在尝试仅在使用参数0时才具有静态函数的特化。

temp_gen.h: temp_gen.h:

#ifndef temp_gen_h
#define temp_gen_h

#include <iostream>

template<int N>
struct my
{
   static void say();
};

template<int N>
void my<N>::say()
{
   std::cout << "generic " << N << std::endl;
}

#endif

temp_spec.h: temp_spec.h:

#ifndef temp_spec_h
#define temp_spec_h

#include <iostream>

#include "temp_gen.h"

template<>
void my<0>::say()
{
   std::cout << "specialized " << 0 << std::endl;
}

#endif

temp_spec.cpp: temp_spec.cpp:

#include "temp_spec.h"

temp_main.cpp: temp_main.cpp:

#include "temp_gen.h"

int main(int argc, char* argv[])
{
   my<0>::say();  //should say "specialized 0"
   my<1>::say();  //should say "generic 0"
}

我相信,由于您的模板特化的实现位于标题中,因此您需要将其标记为inline以便编译器/链接器知道您可以违反一个定义规则。

From within your main.cpp , you did not specialize the template class, this is because you don't include the temp_spec.h . main.cpp ,您没有专门化模板类,这是因为您没有包含temp_spec.h

As Vaughn Cato pointed out (see comments), you should move the definition of the specialized method (which is no template method anymore), to temp_spec.cpp . 正如Vaughn Cato指出的那样(参见注释),你应该将专门方法的定义 (不再是模板方法)移动到temp_spec.cpp

I think (but I'm not an expert at this) you should always put specialization directly below the generic template (in the same header file), because whenever you include this, you also want the specialized ones to be defined, otherwise you will be confused when such errors happen. 我认为(但我不是这方面的专家)你应该总是将特化直接放在通用模板下面 (在同一个头文件中),因为每当你包含它时,你也希望定义专门的,否则你将发生此类错误时会感到困惑。 You can, however, just include the temp_spec.h at the bottom of temp_gen.h . 但是,您可以在temp_spec.h的底部包含temp_gen.h

Also, you don't need the .cpp files for the template headers, as there will never be any code to be compiled separately (template classes are always compiled at the other .cpp file which uses it, and I think duplicates will be removed when linking, causing trouble at link time again when in one case you did not specialize it, one time you did ) 此外,您不需要.cpp文件用于模板标头,因为永远不会有任何代码需要单独编译(模板类总是在使用它的另一个.cpp文件中编译,我认为重复项将被删除链接时, 在链接时再次造成麻烦,在一种情况下你没有专门化,有一次你做了 [This paragraph only applies to the generic template class, not to (fully) specialized classes, as they require some code in their own compilation unit, see comments and the edit above.] [本段仅适用于通用模板类,而不适用于(完全)专用类,因为它们需要在自己的编译单元中使用一些代码,请参阅注释和上面的编辑。

Using the n3337 version of the Standard (emphasis mine): 使用标准的n3337版本(强调我的):

14.7.3 Explicit specialization [temp.expl.spec] 14.7.3显式专门化[temp.expl.spec]

6/ If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; 6 /如果一个模板,一个成员模板或一个类模板的成员被明确地专门化,那么该特化应该在第一次使用该特化之前声明,这将导致隐式实例化发生, 在每个翻译单元中使用发生; no diagnostic is required. 无需诊断。

Because in main the specialization of my<0>::say is not visible, implicit instantiation occurs and you end up in the case above: no diagnostic required (from the compiler). 因为在mainmy<0>::say是不可见的,所以发生了隐式实例化,你最终在上面的情况下: 不需要诊断 (来自编译器)。

Note that a specialization may only be declared after its generic counterpart has been declared. 请注意,只能在声明其通用对应项后声明专门化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM