简体   繁体   中英

Why C++20 doesn't use `requires` to restrict the T for atomic<T>?

A generic std::atomic<T> is required to have a T that is Copy Constructible and Copy Assignable :

[atomics.types.generic]/1

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 .

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, eg 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::atomic in particular, constraining the primary template is simply not an option, given the atomic<shared_ptr<T>> and atomic<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

Code: https://godbolt.org/z/JaCu78

The library specification deliberately avoids using any particular technology to achieve its goals P0788 :

IV. Let's avoid any specification that demands any particular technology by which implementations must comply with Library specifications.

a) Let's permit an implementation to use a requires-clause , an enable_if , a constexpr if , or any other technology or combination of technologies to meet Constraints: specifications.

b) Let's permit an implementation to use static_assert and/or any other technologies to meet Mandates: specifications.

c) Let's permit an implementation to use Contracts attributes [P0542R1] and/or any other technologies to meet Expects: and Ensures: specifications.

d) Let's consider user code that relies on any specific technology on the part of an implementation to be ill-formed, with no diagnostic required.

Which is expanded upon in P1369 .

The goal is to avoid tying the specification of the library to any particular implementation of it. There are cases where you do need to do this - many of the Ranges things do require concepts to work, so they are specified in this way - but for the most part, you don't.

For the user, the important part is the mandated requirements on T . It's not important how those requirements are enforced. It could be a concept, it could be a static_assert , it could be some compiler intrisic, whatever.

For std::atomic in particular, constraining the primary template is simply not an option, given the atomic<shared_ptr<T>> and atomic<weak_ptr<T>> specializations that were added in C++20.

Perhaps you can do something fancier (like an undefined and unconstrained primary template plus a constrained partial specialization), but it adds very little value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM