简体   繁体   English

为什么 C++20 不使用 `requires` 来限制原子的 T<t> ?</t>

[英]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 :通用std::atomic<T>需要具有可复制构造可复制分配T

[atomics.types.generic]/1 [atomics.types.generic]/1

The program is ill-formed if any of如果有以下任何一项,则该程序是格式错误

(1.1) is_trivially_copyable_v<T> , (1.1) is_trivially_copyable_v<T> ,

(1.2) is_copy_constructible_v<T> , (1.2) is_copy_constructible_v<T> ,

(1.3) is_move_constructible_v<T> , (1.3) is_move_constructible_v<T> ,

(1.4) is_copy_assignable_v<T> , (1.4) is_copy_assignable_v<T> ,

or (1.5) is_move_assignable_v<T>或 (1.5) is_move_assignable_v<T>

is false .false的。

Above is not new to C++20.以上对 C++20 来说并不新鲜。 Compilers may use static_assert to issue an error for a non-conforming T.编译器可以使用static_assert为不符合的 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:但是,C++20 可以使用带有requires语法的正式约束来正式要求将上述内容作为类型的一部分,例如:

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? C++20 是否有理由避免为此目的使用形式约束


EDIT: @T.C.编辑: @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.特别是对于std::atomic ,约束主模板根本不是一种选择,因为在 C++20 中添加了atomic<shared_ptr<T>>atomic<weak_ptr<T>>化。

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代码: https://godbolt.org/z/JaCu78

The library specification deliberately avoids using any particular technology to achieve its goals P0788 :库规范故意避免使用任何特定技术来实现其目标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. a) 让我们允许实现使用requires-clauseenable_ifconstexpr if或任何其他技术或技术组合来满足Constraints:规范。

b) Let's permit an implementation to use static_assert and/or any other technologies to meet Mandates: specifications. b) 让我们允许实现使用static_assert和/或任何其他技术来满足Mandates:规范。

c) Let's permit an implementation to use Contracts attributes [P0542R1] and/or any other technologies to meet Expects: and Ensures: specifications. c) 让我们允许实现使用合同属性 [P0542R1] 和/或任何其他技术来满足期望:确保:规范。

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. d) 让我们认为在实现部分依赖于任何特定技术的用户代码是格式错误的,不需要诊断。

Which is expanded upon in P1369 .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.在某些情况下,您确实需要这样做 - 许多 Ranges 事物确实需要概念才能工作,因此它们以这种方式指定 - 但在大多数情况下,您不需要。

For the user, the important part is the mandated requirements on T .对于用户来说,重要的部分是对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.它可能是一个概念,它可能是一个static_assert ,它可能是一些编译器固有的,等等。

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.特别是对于std::atomic ,约束主模板根本不是一种选择,因为在 C++20 中添加了atomic<shared_ptr<T>>atomic<weak_ptr<T>>化。

Perhaps you can do something fancier (like an undefined and unconstrained primary template plus a constrained partial specialization), but it adds very little value.也许你可以做一些更奇特的事情(比如一个未定义和不受约束的主模板加上一个受约束的部分特化),但它增加的价值很少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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