A generic std::atomic<T> is required to have a T that is Copy Constructible and Copy Assignable:
The program is ill-formed if any of
(1.1)
is_trivially_copyable_v<T>,
(1.2)is_copy_constructible_v<T>,
(1.3)is_move_constructible_v<T>,
(1.4)is_copy_assignable_v<T>,
or (1.5)is_move_assignable_v<T>is
false.
The above is not new to C++20. Compilers may use static_assert to issue an error for a non-conforming T.
However, C++20 could use formal constraints with the requires syntax to formally require the above as part of the type, e.g. something like:
template< class T > requires
std::is_trivially_copyable_v<T> &&
std::is_copy_constructible_v<T> &&
std::is_move_constructible_v<T> &&
std::is_copy_assignable_v<T> &&
std::is_move_assignable_v<T>
struct atomic { ... };
Is there a reason why C++20 refrained from using formal constraints for this purpose?
EDIT: @T.C. points out correctly, in an answer below:
For
std::atomicin particular, constraining the primary template is simply not an option, given theatomic<shared_ptr<T>>andatomic<weak_ptr<T>>specializations that were added in C++20.
with an option suggesting that:
Perhaps you can do something fancier (like an undefined and unconstrained primary template plus a constrained partial specialization), but it adds very little value.
Well, there is another option, without the need for an undefined and unconstrained primary template, which is still a bit complex and reduces the value and fun in going with concepts for this usage, but probably better than an undefined base template:
template< class T > requires
std::is_trivially_copyable_v<T> &&
std::is_copy_constructible_v<T> &&
std::is_move_constructible_v<T> &&
std::is_copy_assignable_v<T> &&
std::is_move_assignable_v<T>
|| std::same_as<T, std::shared_ptr<typename T::element_type>>
|| std::same_as<T, std::weak_ptr<typename T::element_type>>
struct atomic { ... };
template< class T >
struct atomic<std::shared_ptr<T>> { ... };
template< class T >
struct atomic<std::weak_ptr<T>> { ... };
// types of all other specializations are Copy Constructible and Copy Assignable