【问题标题】:Catching an exception by value - gcc and clang disagree按值捕获异常 - gcc 和 clang 不同意
【发布时间】:2016-03-23 02:34:29
【问题描述】:

考虑一下这个简短的 sn-p:

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 ) {
            ^

谁是对的?

【问题讨论】:

  • 另外,也许两者都是对的..
  • @xaxxon 我怀疑这样的事情是未指定的。要么它应该是有效的,要么它应该是无效的。无论哪种方式,异常都很奇怪。
  • 嗯,如果您尝试抛出 B,GCC 会正确拒绝它,但如果您尝试抛出 D,则不会。

标签: c++ gcc exception-handling clang language-lawyer


【解决方案1】:

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

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

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

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

这意味着初始化工作如下:

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

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

【讨论】:

  • 并删除示例中的“显式”会使clang接受例外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 2014-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多