成员函数模板需要使用"inline"吗?

7

如果我在非模板类中有一个成员函数模板,而且想要在类外定义它 - 我是否必须使用 "inline" ?

例子:

class A
{
    template <class D>
    void someMethod(D param);
}

template <class D>
/* inline needed here? */ void A::someMethod(D param)
{
}

标准的第3.2.5节说,函数模板不属于单一定义规则。在这方面,成员函数模板是否算作函数模板?

编辑:没有内联时链接器不会报错 - 但仍然有效C++03吗?

编辑:

我目前了解到的是:gcc(和其他编译器)将隐式模板实例导出为弱符号,这意味着如果它们在多个翻译单元中被实例化,则链接时不会发生冲突。由于弱符号并非标准的一部分 - 标准是否以某种方式隐含要求模板实例以此方式行事,并且我可以期望其他符合标准的编译器/链接器组合具有相同的行为吗?

由于内联基本上被优化忽略,但允许在不同的翻译单元中多次定义函数,因此这隐含地将这些函数导出为弱符号。这是否意味着将模板声明为内联是多余的?


1
编译器不能抱怨,因为它一次只看到一个翻译单元,当某个东西在两个翻译单元中定义时,就会发生ODR冲突。 - MSalters
“inline” 有任何语法意义吗?我一直认为它只是编译器的优化建议。 - Philipp
2
@Philipp - inline有语义意义;它告诉编译器,在不同的翻译单元中多次定义相同的内联函数不违反一个定义规则。它还强制实施自己的规则,即所有定义必须相同。 - Pete Becker
只需查看您的C++书籍中的ODR(一个定义规则),一切都会变得更加清晰。 - sellibitze
@MSalters:我指的是gcc/ld组合。 - Hanno S.
显示剩余2条评论
2个回答

0
无论成员函数模板是否是函数模板,它们肯定不是对象或非内联函数,因此一次定义规则不适用。
但实际上,它们确实是函数模板,并且对于标准的其他应用程序(不特定于非成员函数模板)而言,也算作函数模板。

0

inline 作为一个关键字,旨在建议编译器将标记为此类函数作为优化的良好候选项,并帮助实现这种优化,它要求在每个使用它的 CU 中定义该函数 -- 以相同的方式 -- (即使链接器能够进行相同的优化,但如果编译器看到代码,则更容易进行优化,在20年前这种情况很少见)。

您可能希望为函数模板提供此提示,因此标记函数模板定义为内联。如果您不想给出该提示,则不需要使用 inline。

(曾经有一段时间,只有标记为 inline 的函数才被认为是可以进行优化的,但是该关键字尚未遇到像 register 那样的命运,即被编译器普遍忽略,除了其防止变量地址被取的形式意义之外)。


4
“inline”更多是为了避免ODR违规,而不是向编译器提示。一度它被编译器视为好的提示,但后来他们发现人们并不真正了解它,于是将其忽略为性能提示。编译器然后制作了自己的非标准性能提示,以强制进行内联。但后来他们发现人们仍然不知道,因此即使这些非标准形式也往往被编译器忽略... - David Rodríguez - dribeas
@DavidRodríguez-dribeas,我的理解是这只是一个提示。不是强制性的,但也不能完全忽视(就像register一样),它只是在评估应用优化的更或者更复杂的函数中的一个额外参数,并且随着时间的推移可能会变得越来越不重要(这个过程不仅受到内联算法改进的驱动,还受到“仅头文件”的库数量的影响,这些库滥用内联以达到目标,从而降低了内联作为优化驱动因素的价值)。 - AProgrammer
1
@AProgrammer 您的理解部分错误。是的,在实际的内联中,实现可以选择忽略它。但另外,声明一个内联函数实际上要求实现将所有定义(必须是“完全相同”的--草案 n4659,10.1.6/6)折叠成一个。这可以防止链接阶段出现重复符号错误。这在使用内联定义的头文件中非常清楚,该头文件可能被包含在许多地方,使链接器免于内联职责。 - Peter - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接