In the next program, struct B with deleted copy-constructor is thrown and caught by value:
struct B {
B() = default;
B(const B&) = delete;
};
int main() {
try {
throw B{};
}
catch( B ) {
}
}
Clang rejects the code with an expected error:
error: call to deleted constructor of 'B'
catch( B ) {
However GCC accepts the program finely, demo: https://gcc.godbolt.org/z/ed45YKKo5
Which compiler is right here?
Clang is correct. (Thanks for @NathanOliver's comments.)
[except.throw]/3
[except.throw]/5
The exception object is considered as an lvalue, in the copy-initialization of the parameter of the catch clause, the copy constructor is selected. The copy operation might be elided as an optimization; but the copy constructor still has to be present and accessible.
I've reported this as gcc bug 103048.
BTW the copy-initialization of the exception object caused by
throw B{};is fine because of mandatory copy elision (since C++17).