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 considers it ill-formed with:
main.cpp:17:13: error: no matching constructor for initialization of 'B'
catch(B ) {
^
Who's right?
I think this is a gcc bug (and since nobody has downvoted this answer yet, I submitted it as 70375).
Both compilers correctly agree that D{}
should be caught, as per [except.handle]/3, which only checks that B
is a base class of D
.
But the initialization of the handler is defined in [except.handle]/15 as:
The variable declared by the exception-declaration, of type cv
T
or cvT&
, is initialized from the exception object, of typeE
, as follows:
— ifT
is a base class ofE
, the variable is copy-initialized (8.5) from the corresponding base class subobject of the exception object;
That implies that initialization works as:
D __temporary_object{};
B __handler = static_cast<B&>(__temporary_object);
which should be disallowed since B
's copy constructor is marked explicit
(and copy-initialization just doesn't cut it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With