Универсализация обработки исключений

Есть у меня много методов, которые имеют такой вид

try {
   .....
} catch (const MyException & e) {
  return HandleError(e);
} catch (const std::exception & e) {
  return HandleError(e);
}

И функции обработки

HRESULT HandleError(const std::exception & ex, HRESULT code) {
    SetErrorInfo(ex.what());
    return code;
}

HRESULT HandleError(const std::exception & ex) {
    return HandleError(ex, E_UNEXPECTED);
}

HRESULT HandleError(const MyException & ex) {
    return HandleError(ex, ex.code);
}

Вопрос: а нельзя ли сократить catch блок до такого вида

try {
   .....
} catch (const std::exception & e) {
  return HandleError(e);
}

А в самой функции уже принимать решение о том, что это за исключение и что с ним делать

HRESULT HandleError(const std::exception & ex) {
    if (ex is MyException)  // нужен оператор проверки класса-наследника
        return HandleError(ex, dynamic_cast<MyException)(ex).code);
    else
        return HandleError(ex, E_UNEXPECTED);
}

Потому что нужно проверять несколько разных исключений из разных библиотек и у каждого есть свой код ошибки. Не хочется вставлять лесенку идентичных catch. Макросы пока не рассматриваю


Ответы (2 шт):

Автор решения: HolyBlackCat

Конечно, dynamic_cast в помощь. Имея const std::exception &e, делаете вот так:

if (auto m = dynamic_cast<const MyException *>(&e)) {...}

Еще можно в HandleError ничего не передавать, и в ней делать try {throw;} и лесенку из catch-ей. Тогда в вызывающем коде можно просто писать catch (...) {return HandleError();}.

Если беспокоит возможность получить вылет, если вызвать такую функцию вне catch, то посмотрите в сторону std::current_exception - это замена throw;, но позволяет проверить, есть ли сейчас исключение.

→ Ссылка
Автор решения: user7860670

Это делается посредством выбрасывания и повторного перехвата текущего исключения в другом контексте:

try
{
   .....
}
catch (...)
{
   return Handle_Error();
}

HRESULT Handle_Error(void) noexcept
{
    try
    {
        throw;
    }
    catch (const MyException & e)
    {
        return e.code;
    }
    catch (const std::exception & e)
    {
        return E_UNEXPECTED;
    } 
    catch (...)
    {
        return E_UNEXPECTED;
    }
}
→ Ссылка