Следующий код выводит информацию о том, можно ли тривиально скопировать std::atomic<bool>:
#include <atomic>
#include <iostream>
#include <type_traits>
int main(){
std::cout << std::is_trivially_copyable_v<std::atomic<bool>> << "\n";
}
Это дает следующий результат для gcc и clang:
1
Но на MSVC результат:
0
Поведение всех трех компиляторов также демонстрируется здесь с помощью static_assert.
Я думал, что тривиальная возможность копирования в любом случае определяется стандартом.
Какой компилятор прав (или это зависит от реализации)?





Проблема заключается в том, как работает trivyly_copyable. На самом деле вы не можете скопировать атомарный элемент в clang:
https://godbolt.org/z/dr3q3bns5
То же самое относится и к пользовательским некопируемым типам. Таким образом, единственный вопрос заключается в том, разрешено ли trivyly_copyable возвращать true для некопируемого типа. Можно было бы возразить, что, поскольку тип не может быть скопирован, у него нет нетривиальной операции копирования. Хотя мое собственное интуитивное ощущение подсказывает, что это должно давать «false» - в противном случае вам придется проверять is_copyable, а также trivally_copyable в некоторых случаях. Кто-то с большим знанием стандарта, возможно, сможет ответить на этот вопрос - я могу только сказать, что, основываясь на ссылке Cpp (https://en.cppreference.com/w/cpp/types/is_тривиально_copyable), я не знаю Не вижу никаких требований для этого случая.
Спасибо за ответ. Хотя я вижу причину в том, что вы написали, я не уверен в зависимости между копируемостью и тривиальной копируемостью. Смотрите комментарии под ответом Нифила.
См. также: Можно ли тривиально скопировать класс с удаленным копирующим конструктором?
Удаленный конструктор не является нетривиальным.
До принятия резолюции CWG1734 для того, чтобы их можно было тривиально копировать, все конструкторы копирования/перемещения/операторы присваивания должны были быть тривиальными. Это касается std::atomic<bool> (они все удалены)
В новой формулировке его также нельзя было удалять (а в C++20 — «приемлемый», поскольку его ограничения удовлетворены).
GCC и Clang этого не реализуют. См.: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96288 https://github.com/llvm/llvm-project/issues/38398
Означает ли это, что MSVC здесь, а gcc/glang несовместимы?
@wohlstad Да, MSVC в настоящее время верен, а GCC и clang соответствовали требованиям до февраля 2016 года.
Продолжение из комментариев:
en.cppreference.com/w/cpp/atomic/atomic гласит: «std::atomic нельзя ни копировать, ни перемещать». Я бы рекомендовал следовать стандарту.
Также, глядя на исходный код gcc, мы видим, что операторы копирования удалены.
Что касается возвращаемого значения std::is_тривиально_copyable_v, я думаю, что ответ @Juliean дает хорошее объяснение.
априори некопируемость (т. е. отсутствие жизнеспособного конструктора копирования) не означает, что std::trivially_copyable должно быть false. «Тривиально копируемый» - это копирование путем копирования байтов, то есть в обход конструкторов копирования.
Спасибо за ответ. Но я думаю, что, как упоминалось выше, тривиальная возможность копирования — это концепция, отдельная от «нормальной» возможности копирования/перемещения.
@wohlstad Я взял определение отсюда en.cppreference.com/w/cpp/language/… Тривиально копируемый класс — это класс, который имеет хотя бы один подходящий конструктор копирования, конструктор перемещения, оператор присваивания копирования или присваивание перемещения. Каждый подходящий конструктор копирования тривиален. Каждый подходящий конструктор перемещения тривиален. Каждый подходящий оператор присваивания копирования тривиален. Каждый подходящий оператор присваивания перемещения тривиален и имеет неудаляемый тривиальный деструктор.
Я вижу сейчас. Поскольку я не языковой юрист, я не уверен, верна ли ваша интерпретация, но я вижу в этом причину.
имхо, вам следует включить эту цитату в ответ. Заметьте, я не говорил, что вы не правы. Я просто говорю, что ваш ответ содержит молчаливое предположение, что если тип невозможно скопировать с помощью конструктора копирования, то его нельзя тривиально скопировать, я не думаю, что это очевидно и что это должно быть частью ответа.
Кстати, насколько я понимаю цитату, было бы достаточно, если бы класс имел один конструктор перемещения, но не имел другого перемещения или копирования, и если этот конструктор перемещения тривиален, охватываются и другие пункты. (все еще не говорю, что вы неправы, просто пытаюсь прояснить свое замешательство)