将异常从一种类型转换为另一种类型

Hel*_*sel 4 c++ exception-handling

如果有一些框架需要类似的类型的回调

void fcn(F& data);
Run Code Online (Sandbox Code Playgroud)

它可以处理ExF类型的异常.

在我的回调中,我使用的是一些抛出EXL类型异常的第三方库.所以我的回调看起来像

void fcn1(F& data)
{
  try
  {
     // call library
  }
  catch(const ExL& ex)
  {
     ExF exf = make_ExF(ex);
     throw exf;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我想写更多回调fcn2,fcn3,...使用库但不想一直重复相同的try/catch.特别是,也许我会添加另一个

catch(const ExL2& ex)
Run Code Online (Sandbox Code Playgroud)

阻止未来几次回调.我无法更改框架和库中的代码(特别是异常类型).如何避免重复try/catch块?

Sto*_*ica 6

利用这样一个事实:当你处于一个捕获区时,你有一个"当前处理的异常",你可以throw;再次.这允许您将逻辑移动到另一个函数中

void except_translate() {
  try
  {
     throw;
  }
  catch(const ExL& ex)
  {
     ExF exf = make_ExF(ex);
     throw exf;
  }
}

void fcn1(F& data)
{
  try
  {
     // call library
  }
  catch(...)
  {
     except_translate();
  }
}
Run Code Online (Sandbox Code Playgroud)

该技术已知(用于谷歌目的)作为Lippincott功能.它将错误转换逻辑集中到一个位置,因此您可以使用另一个处理程序轻松扩展该功能,并将其转换为使用此实用程序的所有函数.


n. *_* m. 2

编写一个包装器来为您进行翻译。

template <typename Func, typename ... Args>
decltype(auto) translate(Func func, Args&&... args)
{
   try {
      return func(std::forward<Args>(args)...);
   }
   catch(const ExL& ex) {
       ExF exf = make_ExF(ex);
       throw exf;
   }   
}
Run Code Online (Sandbox Code Playgroud)

现在您可以了F data; translate(fcn, data),它的工作方式与 相同fcn1(data)

编辑上面的代码不能作为回调,除非进一步包装它(例如在 lambda 中)。这是另一种方法:

template <typename Res, typename ... Args>
auto
 translate(Res (&func)(Args...)) ->
  std::function<Res(Args...)>
{
   try {
      return [&](Args&& ... args) { return func(std::forward<Args>(args)...); };
   }
   catch(const ExL& ex) {
       ExF exf = make_ExF(ex);
       throw exf;
   }   
}
Run Code Online (Sandbox Code Playgroud)

那么你的回调是translate(fcn).

这两种方法都很通用,如果您只需要包装一种类型的回调,这里有一个简单的方法:

template<void FCT(F& data)>
void translate(F& data)
{
   try {
        FCT(data);
   }
   catch(const ExL& ex) {
       ExF exf = make_ExF(ex);
       throw exf;
   }   
}
Run Code Online (Sandbox Code Playgroud)

回调是translate<fcn>.

(这与您的答案基本相同,但使用独立函数而不是静态成员)。