8

以下是value_or()C++17 标准的定义:

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*不是(即使它没有抛出,可能是因为如果在可选项不包含值时使用它仍然会因 UB 失败) noexcept但是,我们保证永远不会尝试返回包含的值,除非我们有一个。

所以不能value_or声明noexcept给定is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))

4

1 回答 1

6

标准中非常谨慎地使用。那是唯一的障碍。


虽然这回答了这个问题,但下一个问题是“为什么要谨慎使用它”。这是您可能会发现有用的额外信息;如果这是答案的核心,我会包含更多引号而不是链接。纸质数字应该比我使用的特定超链接寿命长,所以就是这样。

N3279是关于 noexcept 的讨论的结论。基本上,任何具有狭窄合同(可以表现出 UB)并且不是移动 ctor 或 dtor 的东西都不会被标记为 noexcept。

以下是指南:

采用的准则

  • 不应抛出任何库析构函数。他们应使用隐式提供的(非抛出)异常规范。
  • LWG 同意不能抛出的具有广泛合同的每个库函数都应标记为无条件 noexcept。
  • 如果库交换函数、移动构造函数或移动赋值运算符是有条件的(即可以通过应用 noexcept 运算符证明不会抛出),那么它应该被标记为有条件的 noexcept。任何其他函数都不应使用有条件的 noexcept 规范。
  • 为与“C”代码(例如 atomics 工具)兼容而设计的库函数可以无条件标记为 noexcept。

我没有参与讨论,但基本上这个想法是编译器可以为这些方法添加异常。

我相信这就是所谓的拉科斯法则。要更改它,请与委员会讨论。

N3248是提出 noexcept 问题的论文。主要是关于测试。

于 2018-05-03T19:38:09.233 回答