以下是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
,则该程序格式错误。
(rvalue重载类似)
value_or
的效果被描述为等同于return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
operator bool
是noexcept
。 operator*
不是 noexcept
(即使它没有抛出,可能是因为如果在可选项不包含值时使用UB,它仍然可能失败)。但是,我们保证永远不会尝试返回包含的值,除非我们有一个。
因此value_or
无法noexcept
{}宣布is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))
?
答案 0 :(得分:6)
虽然这回答了这个问题,但接下来的问题是“为什么要谨慎使用”。这是您可能会发现有用的额外信息;如果这是答案的核心,我会包含更多的引号而不是链接。纸张数字应该比我正在使用的特定超链接更长,所以就有了。
N3279是关于noexcept的讨论的结论。基本上,任何具有狭窄合同(可以展示UB)并且不是移动ctor或dtor的东西都不会被标记为noexcept。
以下是指南:
采纳指南
- 没有库析构函数应该抛出。它们应使用隐式提供的(非抛出)异常规范。
- 每个具有广泛合同的图书馆职能,LWG同意不能抛出,应该被无条件标记为noexcept。
- 如果库交换函数,移动构造函数或移动赋值运算符是条件宽的(即可以通过应用noexcept运算符证明不能抛出),那么它应该被标记为有条件的noexcept。没有其他函数应该使用条件noexcept规范。
- 为与“C”代码(例如原子设施)兼容而设计的库函数可以无条件标记 noexcept。
我不参与讨论,但基本上我的想法是编译器可以为这些方法添加例外。
我相信这被称为Lakos规则。要改变它,请与委员会讨论。
N3248是提出noexcept问题的论文。主要是关于测试。