2016-03-23 15 views
6

はこの短いスニペットを考えてみましょ同意:GCCと打ち鳴らすは

struct B { 
    B() = default; 
    explicit B(B const&) { } 
}; 

struct D : B { }; 

int main() { 
    try { 
     throw D{}; 
    } 
    catch(B) { 
    } 
} 

gccが、このコードを受け付け、打ち鳴らすは、それがで病気に形成されたとみなし:

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

+0

また、両方とも正しいかもしれません。 – xaxxon

+0

@xaxxon私はこれが不特定であると疑う。それが有効であると思われるか無効であると思われるかのいずれかです。いずれにせよ、例外は奇妙です。 – Barry

+0

ええ、GCCは 'B'を投げようとすると正しく拒否しますが、' D'を投げようとすると拒否しません。 –

答えて

4

私はこれはgccのバグです(そして誰もまだこの答えをdownvotedなかったため、私は70375としてそれを提出した)と思います

両方のコンパイラが正しくD{}のみBDの基底クラスであることを確認し[except.handle]/3、あたりとして、キャッチする必要があることに同意するものとします。

しかしハンドラの初期化として[except.handle]/15に定義されている:例外宣言で宣言された変数

は、タイプCVT又はCVT&で、例外オブジェクトから初期化され、 Eのタイプ:
- が基本クラスEである場合、変数は例外オブジェクトの対応する基本クラスサブオブジェクトからコピー初期化(8.5)されます。初期設定として働くことを意味

B年代以来禁止されなければならない
D __temporary_object{}; 
B __handler = static_cast<B&>(__temporary_object); 

はコンストラクタがexplicitをマーク(とコピーの初期化をちょうどそれをカットしていません)されてコピーします。

+0

あなたの例で「明示的」を削除すると、clangは例外を受け入れます。 – xaxxon

関連する問題