具有默认受保护的析构函数的类不是简单可破坏但派生类是?

时间:2017-09-29 07:58:40

标签: c++ c++11 language-lawyer destructor

在下面的例子中,第一个静态断言被触发但不是第二个:

#include<type_traits>
struct A{
 protected:
  ~A()=default;
};
struct B:A{
  //this static assertion fails
  static_assert(std::is_trivially_destructible<A>::value,"");
};
//this static assertion succeeds
static_assert(std::is_trivially_destructible<B>::value,"");

(与GCC,Clang,MSVC,ellcc一起检查)

我不明白为什么A在B内部不能轻易破坏,而B是可以轻易破坏的。这似乎与C ++标准的这两段相矛盾,其中没有提及可访问性:

[class.dtor]

  

如果析构函数不是用户提供的,并且如果:

,则析构函数很简单      

(6.1) - 析构函数不是virtual

     

(6.2) - 其类的所有直接基类都有简单的析构函数,

     

(6.3) - 对于类的所有类型(或其数组)的非静态数据成员,每个都是这样的   class有一个简单的析构函数。

[dcl.fct.def.default]

  

如果用户声明并且没有明确默认或删除,则该功能是用户提供的   在第一次宣言上。

2 个答案:

答案 0 :(得分:4)

简单地说,因为从外部的角度来看,A 根本不可破坏!析构函数是protected,所以如果你有A* ptr },调用delete ptr将无法编译。

答案 1 :(得分:1)

补充Sebastian Redl答案:std::is_trivially_destructible<T>::value==false并不意味着该类型 可以轻易破坏

因此,如果在模板编程中使用它,最好不要使用标准库类型特征,而是直接使用编译器内在函数。例如gcc:

#include<type_traits>
struct A{
    protected:
    ~A(){};
};
struct B:A{
  //Bad: fails while the fact that A is trivially destructible
  //could be used to implement optimized function member in B.
  static_assert(std::is_trivially_destructible<A>::value,"");
  //Good: __has_trivial_destructor actualy return what is name says!!
  static_assert(__has_trivial_destructor(A),"");
};