When throw
occurs in an expression with an operand, its effect is to throw an exception, which is a copy of the operand.
void print_asterisks(int count) {
if (count < 0) {
throw std::invalid_argument("count cannot be negative!");
}
while (count--) { putchar('*'); }
}
When throw
occurs in an expression without an operand, its effect is to rethrow the current exception. If there is no current exception, std::terminate
is called.
try {
// something risky
} catch (const std::bad_alloc&) {
std::cerr << "out of memory" << std::endl;
} catch (...) {
std::cerr << "unexpected exception" << std::endl;
// hope the caller knows how to handle this exception
throw;
}
When throw
occurs in a function declarator, it introduces a dynamic exception specification, which lists the types of exceptions that the function is allowed to propagate.
// this function might propagate a std::runtime_error,
// but not, say, a std::logic_error
void risky() throw(std::runtime_error);
// this function can't propagate any exceptions
void safe() throw();
Dynamic exception specifications are deprecated as of C++11.
Note that the first two uses of throw
listed above constitute expressions rather than statements. (The type of a throw expression is void
.) This makes it possible to nest them within expressions, like so:
unsigned int predecessor(unsigned int x) {
return (x > 0) ? (x - 1) : (throw std::invalid_argument("0 has no predecessor"));
}