Search code examples
c++exceptioninitializationlanguage-lawyer

Catching an exception type with constructor from not-const reference in C++


Consider a struct A with copy-constructor deleted but having instead the constructor from not-const reference. Can one throw an object of A and then catch it by value as in the example program:

struct A {
    A() {}
    A(A&) {}
    A(const A&) = delete;
};

int main() {
    try {
        throw A{};
    }
    catch( A ) {
    }
}

Both GCC and Clang allow such usage. Although MSVC prints an error:

C2316: 'A': cannot be caught as the destructor and/or copy constructor are inaccessible or deleted

Demo: https://gcc.godbolt.org/z/P4c6Ea9fz

Indeed A(const A&) is deleted but A(A&) is accessible here. Is it a wrong diagnostics from MSVC?


Solution

  • This is an MSVC bug: exception objects are never cv-qualified, and handler variables are initialized from an lvalue that refers to them. (The standard doesn’t actually say what the type of that lvalue is, but there’s no reason it should be const-qualified.)