【问题标题】:How to use noexcept operator correctly如何正确使用 noexcept 运算符
【发布时间】:2013-08-09 15:44:03
【问题描述】:

我已经实现了一个智能指针,它使用调用内部对象方法的代理函数存储类型为 T 的对象:

template <class Function, class ...Args, class ...Params> 
inline bool call( Function (T::*function)(Args...) const, Params&& ...args ) const noexcept( noexcept( function ));

但是我发现了一个奇怪的问题——当一个成员函数中产生了一个 std::exception 时,程序被终止了,即使代理函数是在一个 try 块中被调用的。所以我的问题是:使用 noexcept 运算符是否正确,如果不是,在这种情况下我应该如何使用它?

【问题讨论】:

  • C++11 和/或 std::function 中的智能指针有什么问题?
  • 它在某些特殊情况下使用写时复制。它使对存储对象线程的所有调用都是安全的。
  • 参见here,尤其是“如果标记为noexcept 的函数允许在运行时转义未捕获的异常,则立即调用std::terminate。”
  • 是的,谢谢,但据我了解,T::function 和这个代理调用都没有标记为 noexcept。我认为 noexcept 运算符会检测到成员函数可以抛出,因为它没有标记为 noexcept..

标签: c++ c++11 noexcept


【解决方案1】:

根据 C++11 §5.3.7/1:

noexcept 运算符确定对其操作数的求值,它是一个未求值的操作数(第 5 条),是否可以引发异常 (15.1)。

计算表达式 (function) 不会引发异常,因此 noexcept(function) 计算结果为 true。请注意,这与计算表达式 (*function)(std::forward&lt;Params&gt;(args)...) 相同,noexcept((*function)(std::forward&lt;Params&gt;(args)...)) 肯定会计算为 false,因为成员函数指针不是限定的 noexcept

noexcept 是对函数指针类型的限定,例如const。由于call 接受的函数指针类型不是noexcept 限定的,因此复杂的noexcept(noexcept(...)) 将始终评估为noexcept(false)

编辑:下面的内容是不正确的,不可能仅基于函数指针的noexcept 限定来重载,因为“异常规范不被视为函数类型的一部分。 " (§15.4/13)

如果在给定noexcept 限定的成员函数指针时,如果您希望call 成为noexcept,则需要提供重载call(R (T::*)() const noexcept, ...)

【讨论】:

  • 感谢您的回答!所以我应该这样使用它 - noexcept( noexcept( *function(std::forward(args)...)) ?
  • @PavelDavydov 是的,没错。当您在 noexcept 子句、尾随返回类型和函数体中具有完全相同的表达式时,它真的很有趣;)auto foo(...) -&gt; decltype(expr) noexcept(noexcept(expr)) { return expr; }
  • 看起来很酷 =)。我想了一会儿如何让它与返回类型不同于 bool 的函数一起工作,现在我知道了,谢谢!
  • @PavelDavydov 在我的回答中澄清说,对于您的具体情况,call 永远不能是 noexcept
  • @PavelDavydov 再次澄清说我是一个肮脏的骗子,仅凭noexcept 是不可能超载的。
猜你喜欢
  • 2015-10-17
  • 1970-01-01
  • 2022-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
相关资源
最近更新 更多