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

4169. std::atomic<T>'s default constructor should be constrained

Section: 32.5.8.2 [atomics.types.operations] Status: WP Submitter: Giuseppe D'Angelo Opened: 2024-10-15 Last modified: 2024-11-28

Priority: Not Prioritized

View all other issues in [atomics.types.operations].

View all issues with WP status.

Discussion:

The current wording for std::atomic's default constructor in 32.5.8.2 [atomics.types.operations] specifies:

constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);

Mandates: is_default_constructible_v<T> is true.

This wording has been added by P0883R2 for C++20, which changed std::atomic's default constructor to always value-initialize. Before, the behavior of this constructor was not well specified (this was LWG issue 2334(i)).

The usage of a Mandates element in the specification has as a consequence that std::atomic<T> is always default constructible, even when T is not. For instance:

// not default constructible:
struct NDC { NDC(int) {} };

static_assert(std::is_default_constructible<std::atomic<NDC>>); // OK

The above check is OK as per language rules, but this is user-hostile: actually using std::atomic<NDC>'s default constructor results in an error, despite the detection saying otherwise.

Given that std::atomic<T> already requires T to be complete anyhow (32.5.8.1 [atomics.types.generic.general] checks for various type properties which require completeness) it would be more appropriate to use a constraint instead, so that std::atomic<T> is default constructible if and only if T also is.

[2024-11-13; Reflector poll]

Set status to Tentatively Ready after seven votes in favour during reflector poll.

[Wrocław 2024-11-23; Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4993.

  1. Modify 32.5.8.2 [atomics.types.operations] as indicated:

    [Drafting note: There is implementation divergence at the moment; libstdc++ already implements the proposed resolution and has done so for a while.]

    constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
    

    -1- ConstraintsMandates: is_default_constructible_v<T> is true.

    -2- Effects: […]