Является ли std :: is_trivially_copyable неправильным?
Учитывая cppreference и текущий c++ рабочий проект, класс тривиально можно копировать, если:
- Каждый конструктор копирования тривиально или удален
- Каждый конструктор перемещения тривиален или удален
- Каждый оператор присваивания экземпляра тривиально или удален
- Каждый оператор назначения перемещения тривиален или удален
- по крайней мере, один конструктор копирования, конструктор перемещения, оператор присваивания копии или оператор присваивания перемещения не удаляются
-
Тривиальный не удаленный деструктор
Поэтому я придумал этот пример кода:
#include <type_traits>
struct non_trivially_copyable {
non_trivially_copyable(non_trivially_copyable const&) = delete;
non_trivially_copyable& operator=(non_trivially_copyable const&) = delete;
non_trivially_copyable(non_trivially_copyable &&) = delete;
non_trivially_copyable& operator=(non_trivially_copyable &&) = delete;
};
int main()
{
return std::is_trivially_copyable<non_trivially_copyable>::value;
}
Мой класс не удовлетворяет требованию номер 5. Тем не менее он дает мне результат, который мой класс non_trivially_copyable
тривиально можно копировать. Я тестировал его на некоторых онлайн-компиляторах:
Я сомневаюсь, что все реализации ошибочны; так почему я получаю этот результат?
Ответы
Ответ 1
Это было изменено в C++ 17; до этого, non_trivially_copyable
был бы тривиально скопируемым. Ваш класс действительно не тривиально копируется в C++ 17, частью стандарта, который вы называете самим собой.
Однако, похоже, libstdc++ и libc++ не были обновлены, чтобы отразить это. Поэтому, чтобы ответить на ваш вопрос напрямую: эти две реализации действительно ошибаются. Обратите внимание, что ваша ссылка godbolt показывает, что MSVC делает это правильно.
Поскольку это считалось дефектом (см. CWG 1734), это должно измениться и для реализаций более старых версий C++.
Насколько я знаю, одной из основных причин изменения стандарта было создание незаконного доступа memcpy
-ing к атомам и мьютексам.