是否应该将 Lippincott 函数声明为 noexcept?

Should Lippincott functions be declared noexcept?

EDIT: Another way to ask this question, in perspective, is to ask: Should Lippincott functions "catch all"?

Lippincott functions 应该声明 noexcept 吗?有关系吗?

毕竟,这个函数的一个版本所有个异常都被捕获,根据定义不能产生异常。

但是,在我在网上看到的所有示例中,noexcept 从来没有出现过,我想知道我是否遗漏了什么。

示例案例:

foo_Result lippincott() noexcept???
{
    try {
        throw;
    } catch (const MyException1&) {
        return FOO_ERROR1;
    } catch (const MyException2&) {
        return FOO_ERROR2;
    } catch (...) {
        return FOO_UNKNOWN;
    }
}

foo_Result foo_dothing() {
    try {
        foo::DoThing();
        return FOO_OK;
    }
    catch (...) {
        return lippincott();
    }
}

并非所有 catch (...) 执行都来自 C++ 异常。通常建议在任何 catch-all 块中重新抛出异常。这意味着 lippincott 不应该是 noexcept 并且 没有 catch-all 块。

具体来说,在Windows、forced unwinding may execute catch-all blocks之外的C++常用的ABI中:

A catch-all block may be executed during forced unwinding. For instance, a longjmp may execute code in a catch(...) during stack unwinding. However, if this happens, unwinding will proceed at the end of the catch-all block, whether or not there is an explicit rethrow.

特别是 Linux、the blocks are executed, and if not rethrown, the application is terminated. Forced unwinding can happen even in code you completely control on POSIX if you ever call cancellation points 上的 GCC(例如 read)。

除此之外,库执行用户代码的情况并不少见(例如 qsort)。您通常也不想抑制这些异常。

因此,最好的 generic 选项是在 catch-all 块中透明。执行您需要的清理。然后总是重新抛出。

所以你的函数看起来像:

foo_Result lippincott()
{
    try {
        throw;
    } catch (const MyException1&) {
        return FOO_ERROR1;
    } catch (const MyException2&) {
        return FOO_ERROR2;
    } catch (const FooBaseException&) {
        return FOO_UNKNOWN;
    }
}

GCC 确实允许捕捉强制展开,所以如果你真的想要一个 catch-all 并且放弃其他考虑(例如没有用户回调),你可以 first catch abi::__forced_unwind and rethrow.