d'tor 的函数尝试块是否应该允许处理抛出成员变量 d'tor?

Should function-try-block of d'tor allow handling of throwing member-variable d'tor?

我有一个class,它的析构函数是noexcept(false)。我知道它只在某些情况下抛出,我想将它用作 class 和 noexcept 析构函数的成员变量。从 https://en.cppreference.com/w/cpp/language/function-try-block 我读到“从函数体中的任何语句抛出的每个异常,或(对于构造函数)从任何成员或基类构造函数,或(对于析构函数)从任何成员或基类析构函数抛出的异常,都会将控制权转移到处理程序-顺序与常规 try 块中抛出的异常相同。”这让我觉得这应该是正确的:

#include <exception>

class ConditionallyThrowingDtor {
public:
    bool willThrow = true;
    ConditionallyThrowingDtor() = default;
    ~ConditionallyThrowingDtor() noexcept(false) {
        if (willThrow) {
            throw std::exception();
        }
    }
};


class NonThrowingDtor {
public:
    ConditionallyThrowingDtor x;
    ~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        // Ignore because we know it will never happen.
    }
};


int main() {
    // ConditionallyThrowingDtor y; // Throws on destruction as expected.
    NonThrowingDtor x;
}

https://godbolt.org/z/ez17fx (MSVC)

我对 noexcept~NonThrowingDtor() 上的函数尝试块的理解是 noexcept 保证它不会抛出(并且它通过本质上做 try { ... } catch (...) { std::terminate(); } https://en.cppreference.com/w/cpp/language/noexcept_spec。但是带有 catch (...) 且没有额外抛出的函数尝试块应该保证它永远不会抛出。Clang 对此没有问题,但正如神栓 link 所示,MSVC说

<source>(23): warning C4297: 'NonThrowingDtor::~NonThrowingDtor': function assumed not to throw an exception but does
<source>(23): note: destructor or deallocator has a (possibly implicit) non-throwing exception specification
~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        // Ignore because we know it will never happen.
    }

等同于

是“错误的”
~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) {
        throw;
    }

如此简单

~NonThrowingDtor() noexcept
{
    x.willThrow = false;
}

要不传播异常,您必须显式使用 return:

~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        return; // Required to not propagate exception.
    }

不幸的是,msvc 仍然会以这种不会抛出的形式发出警告。
(另一方面,clang/gcc 不对 隐式 发出警告(但对显式发出警告)throw 在这种情况下)。