Catch exception by value - gcc and clang disagree

Consider this short snippet:

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

gcc accepts this code, clang thinks it is poorly formed:

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

Who is right?

+6
source share
1 answer

I think this is a gcc error (and since no one has answered this answer yet, I presented it as 70375 ).

Both compilers correctly agree that D{} should be caught according to [except.handle] / 3 , which only verifies that B is the base class of D

But handler initialization is defined in [except.handle] / 15 as:

A variable declared by an exception declaration, such as cv T or cv T& , is initialized from an exception object of type E as follows: - if T is a base class of E , the variable is initialized with a copy (8.5) from the corresponding subobject of the base class of the exception object;

This means that initialization works like:

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

which should be disabled, since the B constructor of the copy is marked explicit (and copy-initialization just doesn't cut it).

+4
source

All Articles