About C++ throw
It's important to note that C++ throw
(I will only talk about its usage with operand, like throw someExpression;
) is sensitive to type of passed operand. It copies its operand (copy-initializes an auxiliary object from it). And copying is done according to (lexical) type of the operand (not by getting class dynamically).
E.g.:
try {
std::runtime_error myException("Some test message");
std::exception &upcastedMyException = myException;
throw upcastedMyException; //std::exception is thrown
} catch(const std::exception &caught) {
std::cout << caught.what() << std::endl; //will output "std::exception"
}
It differs from other languages, e.g. Java:
try {
RuntimeException myException = new RuntimeException();
Exception upcastedMyException = myException;
throw upcastedMyException; //RuntimeException is thrown
} catch(Exception caught) {
System.out.println(caught.getClass()); //will output "java.lang.RuntimeException"
}
Therefore it's very important that expression passed to C++ throw
has correct type. In my first example, replacing throw upcastedMyException
with (for example) throw static_cast<const std::runtime_error &>(upcastedMyException)
would change the output.
About std::make_exception_ptr
std::make_exception_ptr
, on its hand, is implemented in quite simple way through throw
:
template<class E> std::exception_ptr make_exception_ptr(E e) noexcept {
try {
throw e; //note this line
} catch(...) {
return std::current_exception();
}
}
This means that std::make_exception_ptr
is sensitive to passed template argument; if template argument isn't passed explicitly, then std::make_exception_ptr
is sensitive to (lexical) type of passed function argument (which influences deduction of template argument):
- If you do
std::make_exception_ptr(ex)
in your code (where ex
is declared as const std::exception &
), then std::exception
would be thrown within std::make_exception_ptr
and std::make_exception_ptr
would return std::exception_ptr
related to std::exception
.
- If you do
std::make_exception_ptr(static_cast<const std::logic_error &>(ex))
in your code, then std::logic_error
would be thrown within std::make_exception_ptr
and std::make_exception_ptr
would return std::exception_ptr
related to std::logic_error
.
- If you do
std::make_exception_ptr(static_cast<const std::out_of_range &>(ex))
in your code, then std::out_of_range
would be thrown within std::make_exception_ptr
and std::make_exception_ptr
would return std::exception_ptr
related to std::out_of_range
.