In a library I have a hierarchy of exceptions (RuntimeException -> RecognitionException -> NoViableAltException
). During execution, a NoViableAltException
is thrown, which is caught as below and an exception pointer is created from that:
try {
//code that throws NoViableAltException
} catch (RecognitionException &re) {
std::exception_ptr e = std::make_exception_ptr(re);
reportError(e);
}
The value of e
is used in other places, irrelevant for this question. In reportError()
I actually handle the error:
void reportError(std::exception_ptr e) {
...
try {
std::rethrow_exception(e);
} catch (NoViableAltException &ne) {
reportNoViableAlternative(recognizer, ne);
} catch (InputMismatchException &ne) {
reportInputMismatch(recognizer, ne);
} catch (FailedPredicateException &ne) {
reportFailedPredicate(recognizer, ne);
} catch (RecognitionException &ne) {
recognizer->notifyErrorListeners(ne.getOffendingToken(), ne.what(), e);
}
}
and here's my problem: when I rethrow e
, the NoViableAltException
branch is not taken, but that of the RecognitionException
(the last one). That is surprising and I wonder why this happens. I also tried to catch NoViableAltException*
, to no avail. What is the correct approach to catch the individual exception types?
Don't use
make_exception_ptr
; that's something different (it creates a new exception pointer with a deduced exception type, and your code ends up slicing the caught exception object). Instead, you want to capture the current exception:From documentation for
std::make_exception_ptr
:Unfortunately, copying
e
means you get object slicing (which @Mohamad Elghawi points out is also more prominently mentioned later on that page). When you callstd::make_exception_ptr<RecognitionException>
, it will hold a copy of aRecognitionException
, not any derived class.But you don't need
exception_ptr
at all here. Even thoughreportError
does not have thetry
...catch
in scope, you can still usethrow;
to re-throw the current exception.