C ++模板:检查类型的析构函数是否可以“忽略”

时间:2019-11-08 08:53:09

标签: c++ templates

首先,让我让这个问题更具体。

  

检查类型的析构函数是否可以被“忽略”

我是故意

  

检查类实例消失后是否没有副作用。

我在做什么:

我正在为我们的C ++项目编写垃圾收集库,我需要提高性能。如果我可以检测到传入类型T在销毁时没有副作用,那么我可以检查所有活动对象,其余所有都是垃圾,可以标记为“垃圾”(典型的年轻一代)收集技术)。但是,如果有副作用,我必须扫描每个即将死亡的对象并运行它的析构函数。

例如:

struct S1 {
  int i;
}; // can be ignored

struct S2 {
  int i;
  ~S2() {

  }
}; // can be ignored

struct S3 {
  S3() {
    std::cout << "S3()" << std::endl;
  }
  virtual ~S3() {
    std::cout << "~S3()" << std::endl;
  }
}; // can not be ignored, destructor has side effect

struct S4 {
  S3 s3;
}; // can not be ignored, destructor has side effect(calling s3's destructor) 
// this is the most tricky one I tried and failed.

struct S5 {
  S3 s3;
  ~S5() {

  }
}; // same with S4

struct S6 : public S3 {

};// can not be ignored, super destructor has side effect

struct S7 : public S1 {

};// can be ignored, super destructor does not have side effect

struct S8 {
  virtual ~S8() = default;
}; // can be ignored
// which cannot use is_trivially_destructible

struct S9 : public S8 {

}; // can be ignored

我尝试将is_destructibleis_trivially_destructible合并,但这两个不能满足我的要求。尤其是示例4。

更多: 欢迎使用任何可以解决此问题的编译器特定功能。

1 个答案:

答案 0 :(得分:5)

您需要std::is_trivially_destructible类型的特征。看here。输出与期望值不同的唯一情况是companyNameChangeSubmit。不幸的是,C ++缺乏将空的用户定义的析构函数视为琐碎的构造。

编辑:

无法从上述特征中排除关于S2的条件,因此剩下的唯一选择就是创建自己的特征。这就需要在用户端做额外的工作,没有现成的东西。使用自定义谓词区分用户定义类型的方法有几种:

  1. 通过某种类型的继承存在:

    virtual
  2. 通过presence of a member
  3. (例如,键入别名-标签-transparent comparators的定义方式)

  4. 通过模板专业化(不是1和2独有):

    class my_class : private can_be_forgotten_tag { ... };
    
    template <typename T>
    using can_be_forgotten_v =
        std::is_trivially_destructible<T> ||
        std::is_base_of<can_be_forgotten_tag, T>;
    
  5. 也许更多...

更重要的是,首先应该问的问题是,这是否已不是任何编译器自动为您完成的事情(生成带有或不带有析构函数调用的相同代码)。那样,最好检查一下自己。

P.S。我希望我们一直在考虑新的放置方式,否则会导致内存泄漏。