为什么 C++20 不使用 `requires` 来限制原子 <T> 的 T?
Why doesn't C++20 use `requires` to restrict the T for atomic<T>?
通用 std::atomic<T>
需要具有 T
即 可复制构造 和 可复制分配:
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>
是false
.
以上内容对 C++20 来说并不陌生。编译器可以使用 static_assert
为不符合要求的 T.
发出错误
但是,C++20 可以使用正式的 constraints 和 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 { ... };
C++20 是否有理由避免为此目的使用正式的约束?
编辑: @T.C. 正确指出,在下面的答案中:
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.
好吧,还有另一种选择,不需要 未定义和
不受约束的主模板,它仍然有点复杂,降低了使用概念的价值和乐趣,但可能比未定义的基本模板更好:
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
库规范有意避免使用任何特定技术来实现其目标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.
P1369 对其进行了扩展。
目标是避免将库的规范 绑定到它的任何特定实现。在某些情况下,您确实需要这样做——许多范围的事情确实需要概念才能起作用,所以它们是以这种方式指定的——但在大多数情况下,你不需要。
对于用户来说,重要的是 T
上的强制要求。 如何执行这些要求并不重要。它可能是一个概念,它可能是一个 static_assert
,它可能是一些编译器的本质,无论如何。
特别是对于 std::atomic
,考虑到在 C++20 中添加的 atomic<shared_ptr<T>>
和 atomic<weak_ptr<T>>
特化,限制主模板根本不是一个选项。
也许您可以做一些更奇特的事情(比如未定义和不受约束的主模板加上受约束的偏特化),但它增加的价值很小。
通用 std::atomic<T>
需要具有 T
即 可复制构造 和 可复制分配:
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>
是
false
.
以上内容对 C++20 来说并不陌生。编译器可以使用 static_assert
为不符合要求的 T.
但是,C++20 可以使用正式的 constraints 和 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 { ... };
C++20 是否有理由避免为此目的使用正式的约束?
编辑: @T.C. 正确指出,在下面的答案中:
For
std::atomic
in 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.
有一个选项提示:
Perhaps you can do something fancier (like an undefined and unconstrained primary template plus a constrained partial specialization), but it adds very little value.
好吧,还有另一种选择,不需要 未定义和 不受约束的主模板,它仍然有点复杂,降低了使用概念的价值和乐趣,但可能比未定义的基本模板更好:
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
库规范有意避免使用任何特定技术来实现其目标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
, aconstexpr 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.
P1369 对其进行了扩展。
目标是避免将库的规范 绑定到它的任何特定实现。在某些情况下,您确实需要这样做——许多范围的事情确实需要概念才能起作用,所以它们是以这种方式指定的——但在大多数情况下,你不需要。
对于用户来说,重要的是 T
上的强制要求。 如何执行这些要求并不重要。它可能是一个概念,它可能是一个 static_assert
,它可能是一些编译器的本质,无论如何。
特别是对于 std::atomic
,考虑到在 C++20 中添加的 atomic<shared_ptr<T>>
和 atomic<weak_ptr<T>>
特化,限制主模板根本不是一个选项。
也许您可以做一些更奇特的事情(比如未定义和不受约束的主模板加上受约束的偏特化),但它增加的价值很小。