Почему удаление копирующего конструктора не делает класс некопируемым?

Рейтинг: 3Ответов: 1Опубликовано: 11.06.2023
class A {
    A(const A&) = delete;
};

#include <type_traits>

static_assert(std::is_trivially_copyable_v<A>);

Почему не происходит ошибки компиляции, ведь у класса удалён копирующий конструктор?

Ответы

▲ 2Принят

Как явно, так и неявно удаленные конструкторы удовлетворяют критериям тривиальности.

11.4.4.2 Copy/move constructors [class.copy.ctor]
11 A copy/move constructor for class X is trivial if it is not user-provided and if:
— (11.1) class X has no virtual functions (11.7.2) and no virtual base classes (11.7.1), and
— (11.2) the constructor selected to copy/move each direct base class subobject is trivial, and
— (11.3) for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;
otherwise the copy/move constructor is non-trivial.

А сам класс удовлетворят критериям тривиально копируемости:

11.2 Properties of classes [class.prop]
1 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 (11.4.3, 11.4.4.2, 11.4.5),
— (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 (11.4.6).

Смысл трейта тривиально копируемости заключается в том, что объекты таких типом можно копировать посредством std::memcpy или операций ввода-вывода. Однако это не обязательно подразумевает, что у них должны быть определены конструкторы и/или операторы копирования. Например A можно скопировать std::memcpy, но нельзя обычным образом:

class A
{
    int & x;
};

#include <type_traits>

static_assert(std::is_trivially_copyable_v<A>);
static_assert(not std::is_copy_assignable_v<A>);

online compiler

Разные трейты копируемости работают не по принципу усиления друг друга, как например в цепочке Input, Forward, Bidirectional, RandomAccess Iterator, а независимо.