atomic<T>
is unimplementable for non-is_trivially_copy_constructible T
Section: 32.5.8 [atomics.types.generic] Status: C++20 Submitter: Billy O'Neal III Opened: 2017-08-16 Last modified: 2021-02-25
Priority: 2
View all other issues in [atomics.types.generic].
View all issues with C++20 status.
Discussion:
32.5.8 [atomics.types.generic] requires that T
for std::atomic
is trivially copyable.
Unfortunately, that's not sufficient to implement atomic
. Consider atomic<T>::load
, which
wants to look something like this:
template<class T> struct atomic { __compiler_magic_storage_for_t storage; T load(memory_order = memory_order_seq_cst) const { return __magic_intrinsic(storage); } };
Forming this return statement, though, requires that T
is copy constructible — trivially copyable things
aren't necessarily copyable! For example, the following is trivially copyable but breaks libc++, libstdc++, and msvc++:
struct NonAssignable { int i; NonAssignable() = delete; NonAssignable(int) : i(0) {} NonAssignable(const NonAssignable&) = delete; NonAssignable(NonAssignable&&) = default; NonAssignable& operator=(const NonAssignable&) = delete; NonAssignable& operator=(NonAssignable&&) = delete; ~NonAssignable() = default; };
All three standard libraries are happy as long as T
is trivially copy constructible, assignability is not required.
Casey Carter says that we might want to still require trivially copy assignable though, since what happens when you do an
atomic<T>::store
is morally an "assignment" even if it doesn't use the user's assignment operator.
[2017-11 Albuquerque Wednesday issue processing]
Status to Open; Casey and STL to work with Billy for better wording.
Should this include trivially copyable as well as trivially copy assignable?
2017-11-09, Billy O'Neal provides updated wording.
Previous resolution [SUPERSEDED]:
This resolution is relative to N4687.
Edit 32.5.8 [atomics.types.generic] as indicated:
-1- If
is_trivially_copy_constructible_v<T>
isfalse
, the program is ill-formedThe template argument for. [Note: Type arguments that are not also statically initializable may be difficult to use. — end note]T
shall be trivially copyable (6.8 [basic.types])
Previous resolution [SUPERSEDED]:
This resolution is relative to N4687.
Edit 32.5.8 [atomics.types.generic] as indicated:
-1- If
is_copy_constructible_v<T>
isfalse
or ifis_trivially_copyable_v<T>
isfalse
, the program is ill-formedThe template argument for. [Note: Type arguments that are not also statically initializable may be difficult to use. — end note]T
shall be trivially copyable (6.8 [basic.types])
[2017-11-12, Tomasz comments and suggests alternative wording]
According to my understanding during Albuquerque Saturday issue processing we agreed that we want the type used with the atomics to have non-deleted and trivial copy/move construction and assignment.
Wording note:CopyConstructible
and CopyAssignable
include semantic requirements that are not
checkable at compile time, so these are requirements imposed on the user and cannot be validated by an
implementation without heroic efforts.
[2018-11 San Diego Thursday night issue processing]
Status to Ready.
Proposed resolution:
This resolution is relative to N4700.
Edit 32.5.8 [atomics.types.generic] as indicated:
-1- The template argument for
T
shall meet theCopyConstructible
andCopyAssignable
requirements. Ifis_trivially_copyable_v<T> && is_copy_constructible_v<T> && is_move_constructible_v<T> && is_copy_assignable_v<T> && is_move_assignable_v<T>
isfalse
, the program is ill-formedbe trivially copyable (6.8 [basic.types]). [Note: Type arguments that are not also statically initializable may be difficult to use. — end note]