try-block: try compound-statement handler-seq
function-try-block: try ctor-initializer compound-statement handler-seq
handler-seq: handler handler-seq
handler: catch ( exception-declaration ) compound-statement
exception-declaration: attribute-specifier-seq type-specifier-seq declarator attribute-specifier-seq type-specifier-seq abstract-declarator ...The optional attribute-specifier-seq in an exception-declaration appertains to the parameter of the catch clause ([except.handle]).
void f() {
goto l1; // ill-formed
goto l2; // ill-formed
try {
goto l1; // OK
goto l2; // ill-formed
l1: ;
} catch (...) {
l2: ;
goto l1; // ill-formed
goto l2; // OK
}
}
lab: try {
T1 t1;
try {
T2 t2;
if (condition)
goto lab;
} catch(...) { /* handler 2 */ }
} catch(...) { /* handler 1 */ }
int f(int);
class C {
int i;
double d;
public:
C(int, double);
};
C::C(int ii, double id)
try : i(f(ii)), d(id) {
// constructor statements
} catch (...) {
// handles exceptions thrown from the ctor-initializer and from the constructor statements
}throw "Help!";
try {
// ...
} catch(const char* p) {
// handle character string exceptions here
}
and
class Overflow {
public:
Overflow(char,double,double);
};
void f(double x) {
throw Overflow('+',x,3.45e107);
}
can be caught by a handler for exceptions of type
Overflow:
try {
f(1.2);
} catch(Overflow& oo) {
// handle exceptions of type Overflow here
}
struct C {
C() { }
C(const C&) {
if (std::uncaught_exceptions()) {
throw 0; // throw during copy to handler's exception-declaration object ([except.handle])
}
}
};
int main() {
try {
throw C(); // calls std::terminate() if construction of the handler's
// exception-declaration object is not elided ([class.copy])
} catch(C) { }
}
struct A { };
struct Y { ~Y() noexcept(false) { throw 0; } };
A f() {
try {
A a;
Y y;
A b;
return {}; // #1
} catch (...) {
}
return {}; // #2
}
class Matherr { /* ... */ virtual void vf(); };
class Overflow: public Matherr { /* ... */ };
class Underflow: public Matherr { /* ... */ };
class Zerodivide: public Matherr { /* ... */ };
void f() {
try {
g();
} catch (Overflow oo) {
// ...
} catch (Matherr mm) {
// ...
}
}noexcept-specifier: noexcept ( constant-expression ) noexcept throw ( )
struct B {
virtual void f() noexcept;
virtual void g();
virtual void h() noexcept = delete;
};
struct D: B {
void f(); // ill-formed
void g() noexcept; // OK
void h() = delete; // OK
};
struct A {
A(int = (A(5), 0)) noexcept;
A(const A&) noexcept;
A(A&&) noexcept;
~A();
};
struct B {
B() throw();
B(const B&) = default; // implicit exception specification is noexcept(true)
B(B&&, int = (throw Y(), 0)) noexcept;
~B() noexcept(false);
};
int n = 7;
struct D : public A, public B {
int * p = new int[n];
// D::D() potentially-throwing, as the new operator may throw bad_alloc or bad_array_new_length
// D::D(const D&) non-throwing
// D::D(D&&) potentially-throwing, as the default argument for B's constructor may throw
// D:: D() potentially-throwing
};