2012-08-01 58 views
1

模板专业化的问题是它们被视为正常的函数,因为没有任何地方使用模板参数了。为什么内联模板专业化有帮助,我应该这样做吗?

因此,如果将下面的代码放在头文件中,它首先工作。

template <typename foo> 
void f(foo p) 
{ 
    std::cout << "f one" << std::endl; 
} 

template <> 
void f<int>(int p) 
{ 
    std::cout << "f two" << std::endl; 
} 

但是,如果标题包含在两个文件中,则停止工作。 在这种情况下,我获得(与VS2010)的错误是:

templateordering.obj : error LNK2005: "void __cdecl f<int>(int)" ([email protected]@@[email protected]) already defined in othertu.obj 

这是通过使用在线关键字和其他许多问题提到可以解决的。

template <> 
inline void f<int>(int p) 
{ 
    std::cout << "f two" << std::endl; 
} 

现在,这引起了我两个问题:

  1. 是否有任何其他方式做到这一点?将特殊功能放在源文件中似乎不起作用。可能是因为我需要在头文件中进行某种声明。
  2. 内联实际上做了什么?在互联网上似乎是一个普遍的经验法则,不应该使用内联,因为编译器“可能会以他喜欢的方式在任何情况下内联函数”。因此,如果编译器可能不内联一个我声明为“内联”的函数,为什么这会起作用?
+0

关于你的第一个问题,确实,如果你_do_声明标头中的专业化运作? – 2012-08-01 12:00:27

+0

@CharlesBailey呃,据我所知,只要这个标题只包含在一个翻译单元中就行。但那更像是我的一个实验性猜想。 ;)与内联似乎工作得很好。 – Sarien 2012-08-01 12:01:28

+0

我的意思是_just_是一个声明,而不是仅仅是定义的一部分的声明。 – 2012-08-01 12:07:05

回答

4

是否有任何其他方式做到这一点?将特殊功能放在源文件中似乎不起作用。可能是因为我需要在头文件中进行某种声明。

您需要声明标题中的专业化,就像任何其他功能一样。它取决于你是否定义它内联在标题中,或者(正好一个)源文件中;再一次,就像任何其他功能一样。正如你所说,如果你在标题中定义它,它必须被声明为inline

内联实际上做了什么?

通常,一个定义规则要求的功能,以恰好一个翻译单元在程序中定义。实际上,这意味着你不能在一个头文件中定义一个函数,因为头文件将被包含在多个翻译单元中。

但是,有时您希望或需要在头文件中定义函数 - 例如,如果某些编译器能够看到定义,则它们只能内联函数调用。 inline关键字放宽了规则,以便您可以在多个翻译单元中定义该功能,只要所有定义相同即可。

1

如果您从两个或多个文件中使用相同类型的函数,那么函数将在每个文件中定义。这与在多个源文件中包含的头文件中具有非模板函数定义相同。

将函数标记为inline暗示编译器可以“嵌入”函数,即将函数的主体直接放在函数的调用位置。这意味着该函数并未实际定义。编译器也可以决定不是内嵌函数,在这种情况下inline关键字的行为就像static关键字。

+1

'inline'的行为不像'static' - 内联函数默认具有外部链接。 – 2012-08-01 12:17:26

3

inline可以对的一个定义规则进行一些更改。具体而言,可以在多个翻译单元中定义声明为inline的函数(包括功能模板的显式专门化)(假定在不同翻译单元中的定义相同),并且必须在任何翻译单元中定义它,其中odr - 已使用。这与应用于功能模板(非特定化)的规则是相同版本的odr规则。

您必须在一个翻译单元中定义您的专业化(并在您将其用于其他翻译单元之前进行声明),或者您可以将定义保留在头文件中,但使其成为inline

您专业化的声明是这样的:

template<> void f<int>(int p); 
+0

_odr-used_是什么意思? – Sarien 2012-08-01 12:30:30

+1

@CorporalTouchy:简化一点,它意味着“以需要定义的方式使用”;例如,调用函数或采用其地址。 – 2012-08-01 13:45:30

0

有没有其他方法可以做到这一点? 将特殊功能放在源文件中似乎不起作用。可能是因为我 需要在标题中的某种声明。

是的,如果您将声明和f<int>的定义分开,则应该解决链接器错误。

声明的.h文件中的语法:

template <> 
void f<int>(int p); 
0

是否有任何其他方式做到这一点?

template <> 
static void f<int>(int p) 
{ 
    std::cout << "f two" << std::endl; 
} 

或让他们inline,但使用特殊的编译器选项(如果有的话),以抑制实际内联

什么是内联实际上呢?

最佳答案(S)已经上市:)