有啥东西可以阻止 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 boolnoexceptoperator*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() 和库中的移动构造函数分配有条件地没有例外。 在之前的委员会会议上,我认为他们同意根据他们包装的类型的操作有条件地制作“包装器类型”noexceptstd::optionalstd::variant 就是这样的包装类型。 这是任何“为什么 X 不是 noexcept”问题的好答案 @Yakk 我提到的论文是 [P0884 - Extending the noexcept Policy](wg21.link/P0884],实际上相当简洁。论文引用了std::atomic 和提议的std::function_ref 作为包装类型的示例。我刚刚检查了会议纪要(非公开),并提出了关于 std::optionalstd::variant 的问题,但实际答案是该论文的目的是扩大有条件的 noexcept 政策,而不是做出坚定的决定,因此对于这些类型没有明确的答案。显然委员会强烈接受这篇论文。 @knatten 刚刚重新检查了论文,它实际上只为包装器类型的默认构造函数、复制构造函数和复制赋值运算符提出了条件noexcept,所以不像我认为的那样它不会影响value_or,对不起:/

以上是关于有啥东西可以阻止 std::optional::value_or() 有条件地不例外吗?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以避免 SwiftUI GeometryReader 阻止嵌套视图在列表中增长?

有啥方法可以阻止来自 CANoe 总线上外部设备的特定 CAN 消息?

这里有啥区别阻止它工作?

iOS(Apple):应用程序有啥方法可以要求操作系统阻止该应用程序中的设备?

Xcode:在调试时,有啥方法可以阻止它在最前面的窗口中打开导航器?

有啥能阻止优化尾递归?