模板类的方法是不是隐含内联链接?
Posted
技术标签:
【中文标题】模板类的方法是不是隐含内联链接?【英文标题】:Are methods of templated classes implied inline linkage?模板类的方法是否隐含内联链接? 【发布时间】:2012-07-17 17:08:44 【问题描述】:模板类的方法是隐含的inline
链接(不是在谈论内联优化),还是只是模板化的方法?
// A.h
template<typename T>
class A
public:
void func1(); // #1
virtual void func2(); // #2
template<typename T2> void func3(); // #3
;
template<typename T>
void A<T>::func1() // #1
template<typename T>
void A<T>::func2() // #2
template<typename T>
template<typename T2>
void A<T>::func3<T2>() // #3
以上情况都是inline
【联动】吗? (我应该为其中任何一个明确写inline
)吗?
【问题讨论】:
如果它们都在头文件中,你应该为它们都写inline
。
@user315052 为什么?我认为你不应该标记它们inline
,并让编译器(比你聪明)来决定是否内联。
@JonathonReinhart 这涉及内联链接,而不是复制粘贴类型的内联
@ildjarn:我很确定模板函数和模板类成员函数在这方面是特殊的,我想出的快速测试似乎表明了这一点。我还没有标准的报价。
@Dave:那不是linkage,只是inline
与否。链接影响符号是否在翻译单元中导出,并导出inline
函数(可能是,如果不是static
并且函数在翻译单元中离线生成)。尝试在两个翻译单元中获取内联函数的地址(这将强制进行行外定义,以防您的编译器默认情况下不这样做),然后检查二进制文件中导出了哪些符号,您将看到那个内联函数。
【参考方案1】:
如果模板类的模板函数和成员函数被隐式实例化,则它们是隐式内联1,但要注意模板特化不是。
template <typename T>
struct test
void f();
template <typename T>
void test<T>::f() // inline
template <>
void test<int>::f() // not inline
由于缺乏更好的报价:
必须在隐式实例化 (14.7.1) 的每个翻译单元中定义非导出模板,除非在某个翻译单元中显式实例化相应的特化 (14.7.2);无需诊断
1 仅在允许对它们进行多个定义的意义上,但不允许用于优化目的。您可以手动将它们标记为inline
作为优化器的提示。
请参阅 [basic.def.odr]/13.4
- 模板本身不受 ODR 影响,而不是因为它们隐含为 inline
。
【讨论】:
是的,但是“模板类的方法是内联的,还是只是模板化的方法?”不过,我对专业不了解,很高兴知道! @DavidRodríguez-dribeas:引用并没有说模板隐式内联如果它们被隐式实例化。 @Nawaz:inline
表示如果在程序内的多个翻译单元中定义它,则不违反 ODR 规则。引用声明您需要在程序中提供多个翻译单元(与odr-use一样多)的定义。在程序中提供多个定义的要求似乎很好地暗示了这样做并不违反 ODR,这实际上与 inline
@Nawaz:你也可以通过相反的假设来证明这一点。假设它们不是inline
,则意味着多个定义将违反 ODR,而这反过来又意味着上面的引用迫使您违反 ODR,因为它需要多个定义。假设标准不强制违反标准,前提一定是错误的。
@Nawaz:ODR 规则规定,对于每个非内联函数,整个程序中必须有一个定义,而不是每个 TU。 inline
关键字提示您要执行替换的编译器,但重要的部分是函数的定义必须存在于使用它的所有 TU中在不违反 ODR 的情况下。虽然编译器可以忽略 hint 并产生一个外联定义(大多数编译器即使内联也会产生一个外联定义),但这并不违反 ODR。以上是关于模板类的方法是不是隐含内联链接?的主要内容,如果未能解决你的问题,请参考以下文章