如何组织几十个相似的 try-catch 块?

How to organize dozens of similar try-catch blocks?

我有外部接口,假设有 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 都相同(使用不同参数调用)。

如:

...等等

我有很好的函数 LogIt 可以处理所有这些情况,我们自己的类型 MyException 也可以处理所有这些情况。

而且所有这 20 (40, 60) 个函数的主体看起来都很丑陋,因为 90% 的代码都是完全相似的 try-catch 检查。当开发人员需要修复所有相同的东西时,他就会死去...

是否存在一种方法/实践如何组织它不那么丑陋的方式? 类似于构造函数和析构函数中的 lock-unlock-idiom,但对于 try-catch?

我绝对不想用#define CALLS_CATCH_BLOCK(call_name) ...

也许你可以模板化包装器并通过函数对象调用它:

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 接口使用,您可能仍需要创建单独的方法,但在内部调用模板包装器而不是重复异常处理代码。