Как организовать десятки подобных блоков try-catch?

У меня есть внешний интерфейс, скажем, с 20 аналогичными методами. Каждый может бросить что угодно.

Итак, у меня 20 методов выглядит так:

void Call3Wrapper(int& important_parameter)
{
try
{
external_namespace::IExternal::Call3(important_parameter);
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", "Call3");
throw mynamespace::MyException("Unresolved exception");
}
}

И то же самое для каждого Call1-Call20 (звонки с разными параметрами).

Такие как:

  • void Call7Wrapper (std :: string& important_parameter)
  • void Call12Wrapper (bool& важный_параметр, двойной&
    important_parameter2)

…и так далее.

У меня хорошая функция LogIt для всех этих случаев и нашего собственного типа MyException, который обрабатывает все эти случаи также.

И все эти 20 (40, 60) тел функций выглядят некрасиво, потому что 90% кода в точности аналогичны проверкам try-catch. И разработчик умрет, когда ему нужно будет что-то исправить во всех них …

Существует ли метод / практика, как организовать его менее уродливо?
Что-то вроде lock-unlock-idiom в конструкторах&деструкторы, но для попробовать-поймать?

Я определенно не хочу использовать #define CALLS_CATCH_BLOCK(call_name) ...

0

Решение

Может быть, вы можете шаблонизировать упаковщик и вызвать его через функциональные объекты:

template<typename CALLABLE_T>
void CallWrapper(CALLABLE_T callable, const char* name)
{
try
{
callable();
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", name);
throw mynamespace::MyException("Unresolved exception");
}
}

Тогда вы можете использовать std::bind создать вызываемый объект с параметрами, например:

CallWrapper(std::bind(&external_namespace::IExternal::Call3,
std::ref(important_parameter)),
"Call3");

(или же boost::bind/boost::ref для старых компиляторов)

Обратите внимание, что компилятор по-прежнему будет генерировать экземпляр шаблона для каждого отдельного CALLABLE_T введите, но вам не нужно повторять код.

Также обратите внимание, что таким образом вы также можете вызывать и обрабатывать функции-члены классов и т. Д.


Если это будет использоваться интерфейсом API, вам все равно может понадобиться создать отдельные методы, но вместо этого вызывать шаблонную оболочку вместо повторения кода обработки исключений.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]