是否有任何阻止std :: optional :: value_or()有条件地noexcept?

时间:2018-05-03 18:53:54

标签: c++ language-lawyer c++17 noexcept stdoptional

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

因此value_or无法noexcept {}宣布is_nothrow_copy_constructible<T> && noexcept(static_cast<T>(std::forward<U>(v)))

1 个答案:

答案 0 :(得分:6)

标准中极为谨慎地使用了{p> 。这是唯一的障碍。

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

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

以下是指南:

  

采纳指南

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

我不参与讨论,但基本上我的想法是编译器可以为这些方法添加例外

我相信这被称为Lakos规则。要改变它,请与委员会讨论。

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