Oliv
Oliv

Reputation: 18051

Class with defaulted protected destructor not trivially-destructible but derived class is?

In the following exemple the first static assertion fired but not the second:

#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,"");

(checked with GCC,Clang,MSVC,ellcc)

I don't understand why A can not be trivially_destructible, inside B, while B is trivially destructible. This seems to be in contradiction with these 2 paragraphs of the C++ standard, where accessibility is not mentionned:

[class.dtor]

A destructor is trivial if it is not user-provided and if:

(6.1) — the destructor is not virtual,

(6.2) — all of the direct base classes of its class have trivial destructors, and

(6.3) — for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.

[dcl.fct.def.default]

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.

Upvotes: 1

Views: 661

Answers (2)

Oliv
Oliv

Reputation: 18051

To complement Sebastian Redl answer: std::is_trivially_destructible<T>::value==false does not imply that the type is not trivially-destructible.

So if one use it in template programming, it is much better not to use standard library type traits, but to directly use compiler intrinsic. For exemple with 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),"");
};

Upvotes: 1

Sebastian Redl
Sebastian Redl

Reputation: 71989

Simply put, because from an outside point of view, A is not destructible at all! The destructor is protected, so if you have a A* ptr, calling delete ptr will fail to compile.

Upvotes: 4

Related Questions