按值捕获异常 - gcc 和 clang 不同意



考虑这个简短的片段:

struct B {
    B() = default;
    explicit B(B const& ) { }
};
struct D : B { };
int main() {
    try {
        throw D{};
    }
    catch(B ) {
    }
}

GCC 接受此代码,Clang 认为其格式不正确:

main.cpp:17:13: error: no matching constructor for initialization of 'B'
    catch(B ) {
            ^

谁是对的?

我认为这是一个 gcc 错误(由于还没有人对这个答案投反对票,所以我将其提交为 70375)。

两个编译器都正确地同意应该按照 [except.handle]/3 捕获D{},它只检查BD 的基类。

但是处理程序的初始化在 [except.handle]/15 中定义为:

由异常声明声明的 cv Tcv T& 类型的变量从 E 类型的异常对象初始化,如下所示:
— 如果 TE 的基类,则变量从异常对象的相应基类子对象复制初始化 (8.5);

这意味着初始化的工作方式为:

D __temporary_object{};
B __handler = static_cast<B&>(__temporary_object);

这应该是不允许的,因为B的复制构造函数被标记为explicit(并且复制初始化只是不会削减它)。

最新更新