Consider
#include <iostream>
struct Foo{};
int main(){
try {
throw Foo();
} catch (Foo& e){
std::cout << "Caught";
}
}
The output is Caught
, but why? I would have thought that the catch
should have been const Foo&
. What am I forgetting?
CodePudding user response:
I would have thought that the catch should have been const Foo&.
It doesn't need to be.
I suspect that you are expecting that there would be a problem with binding of an lvalue reference to non-const.
[except.handle]
The variable declared by the exception-declaration, of type cv T or cv T&, is initialized from the exception object, of type E, as follows:
- if T is a base class of E ...
- otherwise, the variable is copy-initialized ([dcl.init]) from an lvalue of type E designating the exception object.
The lifetime of the variable ends when the handler exits, after the destruction of any objects with automatic storage duration initialized within the handler.
Note the highlighted "lvalue". There's no problem binding a non-const lvalue reference to an lvalue.
Sidenotes:
A handler is a match for an exception object of type E if
- The handler is of type cv T or cv T& and E and T are the same type (ignoring the top-level cv-qualifiers), or
Top level cv qualifiers are ignored and don't need to match between thrown object and handler type.
... When the handler declares a reference to an object, any changes to the referenced object are changes to the exception object and will have effect should that object be rethrown.
Catching a reference allows modifying the exception object.
CodePudding user response:
This is because the thrown object is considered in lvalue. [except.handle]/14 states:
The variable declared by the exception-declaration, of type
cv T
orcv T&
, is initialized from the exception object, of typeE
, as follows:
if
T
is a base class ofE
, the variable is copy-initialized ([dcl.init]) from an lvalue of typeT
designating the corresponding base class subobject of the exception object;otherwise, the variable is copy-initialized ([dcl.init]) from an lvalue of type
E
designating the exception object.The lifetime of the variable ends when the handler exits, after the destruction of any objects with automatic storage duration initialized within the handler.