std::atomic<T>
's default constructor should be constrainedSection: 32.5.8.2 [atomics.types.operations] Status: New Submitter: Giuseppe D'Angelo Opened: 2024-10-15 Last modified: 2024-10-31
Priority: Not Prioritized
View other active issues in [atomics.types.operations].
View all other issues in [atomics.types.operations].
View all issues with New 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>
istrue
.
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).
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.
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.
Proposed resolution:
This wording is relative to N4993.
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- Constraints
-2- Effects: […]Mandates:is_default_constructible_v<T>
istrue
.