为什么N3421不提供noexcept限定符?

时间:2014-02-13 11:08:25

标签: c++ c++-standard-library function-object c++14

N3421 - Making Operator Functors greater<>中,std函数对象的新特化是:

template <> struct plus<void> {
  template <class T, class U> auto operator()(T&& t, U&& u) const
  -> decltype(std::forward<T>(t) + std::forward<U>(u));
};

而不是

template <> struct plus<void> {
  template <class T, class U> auto operator()(T&& t, U&& u) const
  noexcept(noexcept(decltype(std::forward<T>(t) + std::forward<U>(u))
                     (std::move(std::forward<T>(t) + std::forward<U>(u)))))
  -> decltype(std::forward<T>(t) + std::forward<U>(u));
};
  • 有没有理由呢?
  • 在此用例中是否遗漏了noexcept

修改:link to the working draft line in github

编辑2:link to libc++ plus specialization

2 个答案:

答案 0 :(得分:6)

现有的LWG指南不鼓励使用noexcept。他们不接受宽合约职能,只有窄合约职能。我不记得究竟是如何界定这些术语的,但我可以告诉你,我出席布里斯托尔会议讨论noexcept并且他们拒绝将其置于某个职能上,因为它是宽合同,我认为是疯了。

因此,出于两个原因,它可能不在这里。首先,委员会和论文作者尚未习惯在每种情况下都考虑noexcept - 与constexpr相似。在这种情况下,论文作者(STL)可能只是忘了添加它。

第二,LWG对接受noexcept的时间有一些疯狂的过度限制。

答案 1 :(得分:4)

@ DeadMG的答案引导我Conservative use of noexcept in the Library,其中说明了以下内容:

  

采纳指南

     
      
  • 没有库析构函数应该抛出。他们应使用隐式提供的(非抛出)异常规范。

  •   
  • LWG同意不能抛出的每个具有广泛合同的函数库函数都应该被标记为无条件noexcept。

  •   
  • 如果库交换函数,移动构造函数或移动赋值运算符是条件宽的(即可以证明不是由   应用noexcept运算符)然后它应标记为   有条件地没有。没有其他功能应该使用条件   noexcept规范。

  •   
  • 为与“C”代码(例如原子设施)兼容而设计的库函数可以标记为无条件noexcept。

  •   

狭义和广义合同定义为:

  
      
  • 函数或操作的广泛合同未指定任何未定义的行为。这样的合同没有先决条件:一个功能   与广泛的合同没有额外的运行时限制   参数,任何对象状态,任何外部全局状态。

  •   
  • 狭义合约是一份不宽的合约。函数或操作的窄契约在调用时会导致未定义的行为   以违反记录合同的方式。这样的合同   指定至少一个涉及其参数object的前提条件   状态,或某些外部全局状态,例如a的初始化   静态对象。

  •   

在该文档的末尾,以前标记为noexcept的运算符仿函数不再是noexcept

因此,如果我理解正确,<functional>中的新运算符仿函数具有广泛的契约,但有时可能会依赖于它们所处理的类型。因此,它们不是无条件的noexcept(true)。因此,由图书馆实施者决定:

  

将它们的使用留作图书馆供应商的实施质量   功能,直到我们有更多的经验。