class with deleted destructor considered trivially copyable?

Viewed 115

This compiles both with gcc and clang

#include <type_traits>

struct A {
    ~A() = delete;
};

static_assert(std::is_trivially_copyable_v<A>);
int main() { }

Is a class with deleted destructor trivially copyable?

2 Answers

A trivially copyable class may not have a deleted constructor

Given the title and the future readers of this thread: the standard is entirely clear on that A defined as

struct A {
    ~A() = delete;
};

is not a trivially copyable class, as per [class.prop]/1, particularly /1.3

A trivially copyable class is a class:

  • (1.1) that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),
  • (1.2) where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
  • (1.3) that has a trivial, non-deleted destructor ([class.dtor]).

As to why both GCC and Clang does not respect this, in Clang bug report

Richard Smith comments

(R. Smith) This is DR1734, which Clang (and apparently GCC) does not yet implement.

after which the discussion goes over to why this is hard to implement (ABI compatibility concerns), but without any mentioning of actually attempting to file a DR or similar to change or challenge the standard text; e.g.:

(R. Smith) [...] The part of the ABI I was referring to is "POD for the purpose of layout", for which various different targets use different rules, and the four that I listed above base their rule on Clang's broken notion of "trivially-copyable".

Thus, from language lawyer perspective the standard is very clear on this topic: A is not trivially copyable.

I suppose the destructor of A is implicitly deleted, and = delete; has no affect and is not counted in std::is_trivially_copyable_v<A>.

The same happens with the extended example

#include <type_traits>

struct A {
    int a;
    int b;
    ~A() = delete;
};

static_assert(std::is_trivially_copyable_v<A>);
int main() { }

The implicitly-declared or defaulted destructor for class T is defined as deleted (since C++11) if any of the following is true:

  • has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)

...

= delete does not change the destructor's attribute "Deleted implicitly-declared destructor", thus the class A above is identical to the class A below:

struct A {
    int a;
    int b;
};

The condition "Has a trivial non-deleted destructor" is true.


I have the only thought. Since the implicit destructor is unavailable already, the requirement Has a trivial non-deleted destructor is not violated by = delete of the unavailable destructor, nothing to delete. But = delete makes a user-declared implicit deleted destructor (makes it available). Let look at int main() { A a; } Compilers do not call unavailable destructors like in your example of A, but have to call user-declared destructors like in my example of A, and it is deleted (being available).

Related