3012. 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.

  1. Edit 32.5.8 [atomics.types.generic] as indicated:

    -1- If is_trivially_copy_constructible_v<T> is false, the program is ill-formedThe template argument for T shall be trivially copyable (6.8 [basic.types]). [Note: Type arguments that are not also statically initializable may be difficult to use. — end note]

Previous resolution [SUPERSEDED]:

This resolution is relative to N4687.

  1. Edit 32.5.8 [atomics.types.generic] as indicated:

    -1- If is_copy_constructible_v<T> is false or if is_trivially_copyable_v<T> is false, the program is ill-formedThe template argument for T shall be trivially copyable (6.8 [basic.types]). [Note: Type arguments that are not also statically initializable may be difficult to use. — end note]

[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.

  1. Edit 32.5.8 [atomics.types.generic] as indicated:

    -1- The template argument for T shall meet the CopyConstructible and CopyAssignable requirements. If is_trivially_copyable_v<T> && is_copy_constructible_v<T> && is_move_constructible_v<T> && is_copy_assignable_v<T> && is_move_assignable_v<T> is false, 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]