【问题标题】:Why do templates specialisations need to be inlined?为什么需要内联模板特化?
【发布时间】:2018-07-02 07:50:36
【问题描述】:

我指的是这个答案:

https://stackoverflow.com/a/4447057/930315

我遇到了与引用问题的 OP 类似的问题, 有一个功能

template<typename T>
void func(T& val);

及其专业化

template<>
void func<mytype>(mytype& val);

导致重复符号链接器错误(这些方法在我的标题末尾包含的“.tpp”文件中实现)。 将inline 添加到专用函数解决了该问题。为什么?

【问题讨论】:

  • 您追求的“原因”是什么?指出 C++ 标准所说的内容或理由?
  • .tpp。这是一种非常时髦的编程风格。为此提出了这个问题。您是否针对特定的 C++ 标准?目前模板的发展速度非常快。
  • 嗯,这个想法是函数模板特化不再是模板 - 所有模板参数都是已知的,因此它像常规函数一样编译。我正在尝试查找相关的标准报价。
  • 不要粗鲁,但我问了你一个“或”问题,你回答“是”。
  • @StoryTeller。对此感到抱歉——我想到了“基本原理”部分。

标签: c++ templates inline template-meta-programming template-specialization


【解决方案1】:

这将在没有内联的情况下工作:

file1.h

template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);

file1.cpp

template<> void func<int>(int& ) {}

但是如果你在头文件中定义模板特化,那么你可能会违反ODR

【讨论】:

    【解决方案2】:

    好吧,如果您想要关于此的标准报价,那将在 [temp.expl.spec]/12 结束

    函数或变量模板的显式特化是 仅当使用 inline 说明符声明或定义为 inline 时 删除,并且与它的函数或变量无关 模板是内联的。 [ 示例:

    template<class T> void f(T) { /* ... */ }
    template<class T> inline T g(T) { /* ... */ }
    
    template<> inline void f<>(int) { /* ... */ }   // OK: inline
    template<> int g<>(int) { /* ... */ }           // OK: not inline 
    

    — 结束示例 ]

    这就是你必须这样做的原因。它是独立的,因为我认为不这样做会造成不必要的限制,正如 Yola 所证明的那样。

    【讨论】:

      【解决方案3】:

      根据c++标准中的3.2:4条款

      每个程序都应该包含每个非内联的定义 在该程序中使用 odr 的函数或变量;没有诊断 必需的。定义可以显式地出现在程序中,它可以 可以在标准库或用户定义库中找到,或者(当 适当)它是隐式定义的(见 12.1、12.4 和 12.8)。内联函数应在使用它的每个翻译单元中定义。

      这解释了为什么在未内联声明专用函数时会出现链接时错误。该程序将包含专用函数的多个定义,每个模块中的一个定义包括 .tpp 文件,这打破了标准的条件。在声明专用函数inline 时,它将使函数满足同一子句的第二部分,即必须在使用该函数的每个模块中定义一个内联函数。

      当参数化函数没有被特化时,它被第 3.2:6 节所涵盖:

      类类型可以有多个定义(第 9 条), 枚举类型(7.2),具有外部链接的内联函数(7.1.2), 类模板(第 14 条),非静态函数模板(14.5.6), 类模板的静态数据成员(14.5.1.3),成员函数 类模板 (14.5.1.1),或模板特化 程序中未指定模板参数(14.7、14.5.5) 前提是每个定义出现在不同的翻译单元中

      该子句声明,只要代码中没有指定至少一个模板参数,就可以对同一个模板函数进行多个定义。这是为了允许仅根据本地信息来决定是否应在模块中实例化参数化函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-28
        • 1970-01-01
        • 2012-11-20
        • 2021-01-01
        相关资源
        最近更新 更多