Ответ 1
Обновить. Предлагаемое разрешение CWG 1734, в настоящее время в состоянии "готово", изменит [class]/p6:
Тривиально-совместимый класс - это класс:
- где каждый конструктор копирования, конструктор перемещения, оператор присваивания копии и оператор назначения перемещения (12.8 [class.copy], 13.5.3 [over.ass]) либо удаляется, либо тривиально,
- который имеет по крайней мере один неиспользуемый конструктор копии, перемещает конструктор, оператор присваивания копии или оператор переноса перемещения, и
- который имеет тривиальный, не удаленный деструктор (12.4 [class.dtor]).
Это отображает такие классы, как
struct B {
B() = default;
B(const B&) = delete;
B& operator=(const B&) = delete;
};
больше не копируется тривиально. (Классы такого типа включают в себя примитивы синхронизации, такие как std::atomic<T>
и std::mutex
.)
Однако A
в OP имеет неявно объявленный, не удаленный оператор назначения копирования, который является тривиальным, поэтому он остается тривиально с возможностью копирования.
Оригинальный ответ для ситуации, предшествующей CWG1734, сохраняется ниже для справки.
Да, несколько противоречиво, он тривиально можно копировать. [Класс]/p6:
Тривиально-скопируемый класс - это класс, который:
- не имеет нетривиальных конструкторов копирования (12.8),
- не имеет нетривиальных конструкторов перемещения (12.8),
- не имеет нетривиальных операторов присваивания копий (13.5.3, 12.8),
- не имеет нетривиальных операторов присваивания перемещения (13.5.3, 12.8) и
- имеет тривиальный деструктор (12.4).
[class.copy]/р12:
Конструктор копирования/перемещения для класса X тривиален, если он не является предоставляемый пользователем, его список параметров-параметров эквивалентен parameter-type-list неявного объявления, а если
- класс X не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1) и
- класс X не имеет нестатических элементов данных с нестабильным типом, а
- конструктор, выбранный для копирования/перемещения каждого подобъекта прямого базового класса, тривиален и
- для каждого нестатического элемента данных X, относящегося к типу класса (или его массиву), конструктор, выбранный для копирования/перемещения этого элемента, тривиальным;
Аналогично ([class.copy]/p25):
Оператор присваивания копирования/перемещения для класса X тривиален, если он не является предоставляемый пользователем, его список параметров-параметров эквивалентен parameter-type-list неявного объявления, а если
- класс X не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1) и
- класс X не имеет нестатических элементов данных с нестабильным типом, а
- оператор присваивания, выбранный для копирования/перемещения каждого подобъекта прямого базового класса, тривиален и
- для каждого нестатического элемента данных X, относящегося к типу класса (или его массиву), оператор присваивания, выбранный для копирования/перемещения этого элемента, тривиальным;
[class.dtor]/р5:
Деструктор тривиален, если он не предоставляется пользователем, и если:
- деструктор не
virtual
,- все прямые базовые классы его класса имеют тривиальные деструкторы, а
- для всех нестатических членов данных своего класса, которые относятся к типу класса (или его массиву), каждый такой класс имеет тривиальный деструктор.
[dcl.fct.def.default]/р5:
Функция предоставляется пользователю, если она объявлена пользователем и не явно по умолчанию или удалено в его первом объявлении.
В самом деле, это был источник проблем для самого комитета, потому что в соответствии с текущим определением atomic<T>
(наряду с мьютексами и условием переменные) будет тривиально скопируемым. (И, очевидно, разрешить кому-то memcpy
через atomic
или mutex
без вызова UB было бы... просто сказать серьезно проблематично.) См. Также N4460.