为什么 std::uncaught_exception 会变成 std::uncaught_exceptions?

Why will std::uncaught_exception change to std::uncaught_exceptions?

我刚注意到

http://en.cppreference.com/w/cpp/error/uncaught_exception

C++17 将用 std::uncaught_exceptions() 替换 std::uncaught_exception(),其中 returns 为 bool,其中 returns 为 int .

此处描述了对标准的补充:

http://isocpp.org/files/papers/n4259.pdf

它没有提供基本原理,但确实说明了

[Note: When uncaught_exceptions() > 0, throwing an exception can result in a call of std::terminate() (15.5.1). – end note]

这是奇怪的模糊。

发生这种变化的原因是什么?在 C++17 或标准的某些未来版本中是否可能存在多个活动异常?

介绍这个的论文是 n4152,其中有基本原理(通常归结为 "make ScopeGuard work")

引用,

as documented at least since 1998 in Guru of the Week #47, it means code that is transitively called from a destructor that could itself be invoked during stack unwinding cannot correctly detect whether it itself is actually being called as part of unwinding. Once you’re in unwinding of any exception, to uncaught_exception everything looks like unwinding, even if there is more than one active exception.

this uses information already present in major implementations, where current implementations of ScopeGuard resort to nonportable code that relies on undocumented compiler features to make ScopeGuard “portable in practice” today. This option proposes adding a single new function to expose the information that already present in compilers, so that these uses can be truly portable

PS:这是一个如何使用特定于编译器的信息来实现此功能的示例:https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp

对于使用它的一个简单示例,只需查看 boost.log 的 "record pump"(参见 boost/log/detail/format.hpp and boost/log/sources/record_ostream.hpp):它使 BOOST_LOG(lg) << foo(); 可以如果 foo 不抛出,则登录它创建的 guard 对象的析构函数,也就是说,如果调用析构函数时运行中的异常数不大于调用构造函数时的异常数。

std::uncaught_exception() 只检测堆栈是否正在展开。在 Herb Sutter 的一篇论文中,他指出这并不能可靠地表明存在活跃的异常。 Herb 认为这 "almost" 有用。我遇到过这种确实有歧义的情况,这就是导致我出现这种情况的原因post。

std::uncaught_exceptions() 被指定为返回活动异常的数量,这实际上是有用的。

请注意 std::uncaught_exception() 对 debug/loginfo 仍然有用。它可以帮助确定异常的起源。不过功能上我是同意的,没啥用。