有啥东西可以阻止 std::optional::value_or() 有条件地不例外吗?
Posted
技术标签:
【中文标题】有啥东西可以阻止 std::optional::value_or() 有条件地不例外吗?【英文标题】:Does anything prevent std::optional::value_or() from being conditionally noexcept?有什么东西可以阻止 std::optional::value_or() 有条件地不例外吗? 【发布时间】:2018-10-14 04:24:06 【问题描述】:这是 C++17 标准中value_or()
的定义:
template <class U> constexpr T value_or(U&& v) const&;
效果:相当于:
return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
备注:如果
is_copy_constructible_v<T> && is_convertible_v<U&&, T>
是false
,则程序格式错误。
(右值重载类似)
value_or
的效果描述为等同于return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
operator bool
是 noexcept
。 operator*
是 not noexcept
(即使它没有抛出,可能是因为如果在可选项不包含值时使用它仍然会因 UB 失败)。但是,我们保证永远不会尝试返回包含的值,除非我们有一个。
那么在给定is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))
的情况下,不能将value_or
声明为noexcept
吗?
【问题讨论】:
C++ 标准中没有大量使用条件 noexcept 可能会“算”为阻止它在这里使用的东西。 @Yakk 我认为这回答了提出的问题,但另一个问题立即出现:为什么它没有被广泛使用? 【参考方案1】:noexcept 在c++ 标准中的使用非常谨慎。这是唯一的障碍。
虽然这回答了问题,但下一个问题是“为什么要谨慎使用它”。这是您可能会发现有用的额外信息;如果这是答案的核心,我会包含更多引号而不是链接。论文编号应该比我使用的特定超链接的寿命长,所以就是这样。
N3279 是关于 noexcept 的讨论的结论。基本上,任何具有狭义合同(可以表现出 UB)并且不是移动 ctor 或 dtor 的东西都不会被标记为 noexcept。
以下是指南:
采用的准则
不应抛出任何库析构函数。他们应使用隐式提供的(非抛出)异常规范。 LWG 同意不能抛出的具有广泛合同的每个库函数都应标记为无条件 noexcept。 如果库交换函数、移动构造函数或移动赋值运算符是有条件的(即可以通过应用 noexcept 运算符证明不会抛出),则应将其标记为有条件的 noexcept。任何其他函数都不应使用有条件的 noexcept 规范。 为与“C”代码(例如原子工具)兼容而设计的库函数可能被标记为无条件 没有例外。
我没有参与讨论,但基本上这个想法是编译器可以向这些方法添加异常。
我相信这就是所谓的拉科斯法则。要更改它,请与委员会讨论。
N3248 是提出 noexcept 问题的论文。主要是关于测试。
【讨论】:
此问题的相关指南在第 2 页:只有swap()
和库中的移动构造函数分配有条件地没有例外。
在之前的委员会会议上,我认为他们同意根据他们包装的类型的操作有条件地制作“包装器类型”noexcept
。 std::optional
和 std::variant
就是这样的包装类型。
这是任何“为什么 X 不是 noexcept”问题的好答案
@Yakk 我提到的论文是 [P0884 - Extending the noexcept
Policy](wg21.link/P0884],实际上相当简洁。论文引用了std::atomic
和提议的std::function_ref
作为包装类型的示例。我刚刚检查了会议纪要(非公开),并提出了关于 std::optional
和 std::variant
的问题,但实际答案是该论文的目的是扩大有条件的 noexcept
政策,而不是做出坚定的决定,因此对于这些类型没有明确的答案。显然委员会强烈接受这篇论文。
@knatten 刚刚重新检查了论文,它实际上只为包装器类型的默认构造函数、复制构造函数和复制赋值运算符提出了条件noexcept
,所以不像我认为的那样它不会影响value_or
,对不起:/以上是关于有啥东西可以阻止 std::optional::value_or() 有条件地不例外吗?的主要内容,如果未能解决你的问题,请参考以下文章
有啥方法可以避免 SwiftUI GeometryReader 阻止嵌套视图在列表中增长?
有啥方法可以阻止来自 CANoe 总线上外部设备的特定 CAN 消息?
iOS(Apple):应用程序有啥方法可以要求操作系统阻止该应用程序中的设备?