【问题标题】:Do template specialized class with static methods occupy storage?具有静态方法的模板专用类是否占用存储空间?
【发布时间】:2018-05-14 13:39:30
【问题描述】:

(我很抱歉标题凌乱。我很乐意接受改进它的建议。)

我会尽量做到直截了当。我有以下代码:

file1.hpp

template <class val_t>
struct MatOps;

file2.hpp:

#include "file1.hpp"
template <> struct MatOps<float>{
  static void method1(){
    // Do something
  }
  static void method2(){
    // Do something
  }
  static void method3(){
    // Do something
  }
}

文件3.hpp:

#include "file1.hpp"
template <> struct MatOps<double>{
  static void method1(){
    // Do something different
  }
  static void method2(){
    // Do something different
  }
  static void method3(){
    // Do something different
  }
}

main.cpp

#include "file2.hpp"
#include "file3.hpp"

int main(){
  float a,b,c,d;

  MatOps<float>::method1(a,b,...);
  MatOps<float>::method2(c,d,...);

  return 0;
}

问题:

  1. 使用显式特化MatOps&lt;double&gt;。然而,MatOps&lt;double&gt; 真的被实例化了吗?或更粗略地说:包含 file3.hpp 是否占用任何存储空间?
  2. 使用MatOps&lt;float&gt;::method3(),但我正在使用类中的其他方法。由于我明确使用MatOps&lt;float&gt;,编译器是否为MatOps&lt;float&gt;::method3() 生成代码?

理由:我被要求遵循 MISRA C++:2003 标准中的一些准则。虽然已经过时,但我被鼓励使用其中合理的任何东西。特别是,有一条规则如下:

头文件应用于声明对象、函数、内联函数、函数模板、typedef、宏、类和类模板,并且不应包含或生成占用的对象或函数(或函数或对象的片段)的定义存储。

头文件被认为是通过#include 指令包含的任何文件,无论名称或后缀如何。

我的代码被大量模板化,因此我可以根据此规则包含任何文件。当我进行完全专业化时,我的问题就出现了(我只做其中两个:file2.hpp 和 file3.hpp 中列出的那些)。什么是完整的模板特化?即使不使用,是否也会为它们生成代码?最终,它们会占用存储空间吗?

【问题讨论】:

  • "是 MatOps 实际实例化的"一个对象只能在创建时实例化。如果你不做一个;它永远不会被制造出来;与不制作 MatOps<:vector>> 的方式相同
  • 通常的定义是只有变量占用“存储”。代码存储在计算机中,但通常不称为存储。您能否就您的问题澄清上述内容。此外,在类(甚至是模板)中定义的任何方法都是 inline 函数,因此引用中的 para1 适用。
  • @UKMonkey 由于对象没有被实例化,我可以安全地假设没有为matOps&lt;double&gt; 生成代码吗?那么MatOps&lt;float&gt;::method3()呢?我正在创建MatOps&lt;float&gt;,但没有使用第三种方法
  • “最终,它们会占用存储空间吗?”对于发布版本;不;链接器会将未使用的函数定义装箱。对于调试版本 - 也许。
  • Class template 部分中,您可以在隐式实例化 下看到“...,除非在程序中使用该成员,否则它不会被实例化,并且不会不需要定义。”基本上,编译器甚至不会强制检查此类函数的定义,除非它被使用。所以,回答 2.,他们不会为 MatOps&lt;float&gt;::method3() 生成代码。

标签: c++ templates template-specialization misra explicit-specialization


【解决方案1】:

为了回答你的第一个问题,我引用cppreference.com的以下内容:

类模板本身不是类型、对象或任何其他 实体。不会从仅包含的源文件生成代码 模板定义。为了让任何代码出现,模板必须 被实例化:必须提供模板参数,以便 编译器可以生成一个实际的类(或函数,从一个函数 模板)。

包含file3.hpp 不会自行生成代码。

至于第二部分,同样来自同一页面,

当代码在上下文中引用模板时需要完全 定义类型,或者当类型的完整性影响代码时, 并且这个特定类型没有被显式实例化, 发生隐式实例化。例如,当这个对象 type 被构造,但不是当指向该类型的指针被构造时 构建。

这适用于类模板的成员:除非该成员是 在程序中使用,它没有被实例化,也没有 需要一个定义。

除非您对类模板进行显式实例化,否则类模板的各个成员函数将不会被实例化,,编译器不会为MatOps&lt;float&gt;::method3() 生成代码。

【讨论】:

    猜你喜欢
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多