This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3633. Atomics are copy constructible and copy assignable from `volatile` atomics

Section: 31 [atomics] Status: New Submitter: Wesley Maxey Opened: 2021-11-05 Last modified: 2022-01-29

Priority: 3

View all other issues in [atomics].

View all issues with New status.

Discussion:

The specification of `atomic` and `atomic<T*>` (in 31.8.1 [atomics.types.generic.general] and 31.8.5 [atomics.types.pointer]) explicitly deletes the following functions:

>     atomic(const atomic&) = delete;
>     atomic& operator=(const atomic&) = delete;
>     atomic& operator=(const atomic&) volatile = delete;

The intent is to make atomic objects not copyable, so that initializing an atomic object from another atomic, or assigning an atomic object with a value from another atomic, must be an explicit operation.

We also explicitly support `volatile` objects of types that are specializations of `std::atomic`; some of the functions that are vital for the support of volatile atomics are the following conversion operators:

>     operator T() const volatile noexcept; // for non-pointers
>     operator T*() const volatile noexcept; // for pointers

The presence of this conversion operator means that all the statements in the following piece of code compile successfully today, despite the deleted functions mentioned earlier:

>     volatile std::atomic<int> a;
>     volatile std::atomic<int> b(a);
>     std::atomic<int> c(a);
>     b = a;
>     c = a;

However, if `a` is not a volatile object, none of the last four lines compile.

[2022-01-29; Reflector poll]

Set priority to 3 after reflector poll.
This PR would allow

    atomic<int> x, y = std::move(x);

because const volatile& doesn't bind to rvalues. It sounds like we'll need to delete both const volatile& and const volatile&&.

Proposed resolution:

This wording is relative to N4901.

1. Modify 31.8.1 [atomics.types.generic.general], class template `atomic` synopsis, as indicated:

   >     […]
   >     atomic(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) volatile = delete;
   >     […]

2. Modify 31.8.3 [atomics.types.int], class template `atomic<integral>` specialization synopsis, as indicated:

   >     […]
   >     atomic(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) volatile = delete;
   >     […]

3. Modify 31.8.4 [atomics.types.float], class template `atomic<floating-point>` specialization synopsis, as indicated:

   >     […]
   >     atomic(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) volatile = delete;
   >     […]

4. Modify 31.8.5 [atomics.types.pointer], class template `atomic<T*>` partial specialization synopsis, as indicated:

   >     […]
   >     atomic(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) = delete;
   >     atomic& operator=(const volatile atomic&) volatile = delete;
   >     […]