在C++ 11中,如何根据返回类型对一个函数对象进行专门化?

Joh*_*oty 5 c++ templates function-templates c++11

我在C++ 11中有一个包装函数,设计用于lambdas,如下所示:

template<typename Func>
int WrapExceptions(Func&& f)
{
  try
  {
    return f();
  }
  catch(std::exception)
  {
    return -1;
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以这样称呼它:

int rc = WrapExceptions([&]{
  DoSomething();
  return 0;
});
assert(rc == 0);
Run Code Online (Sandbox Code Playgroud)

生活还可以.但是,我想要做的是重载或专门化包装函数,这样当内部函数返回void时,外部函数返回默认值0,例如:

int rc = WrapExceptions([&]{
  DoSomething();
});
assert(rc == 0);
Run Code Online (Sandbox Code Playgroud)

我可以在C++ 11中实际执行此操作吗?我不能为我的生活思考如何.

Jar*_*d42 7

您可以使用SFINAE:

  • std::result_of

    template<typename Func>
    typename std::enable_if<
        std::is_convertible<typename std::result_of<Func()>::type, int>::value,
        int
        >::type
    WrapExceptions(Func&& f)
    {
      try { return f(); }
      catch(std::exception) { return -1; }
    }
    
    template<typename Func>
    typename std::enable_if<
        std::is_same<void, typename std::result_of<Func()>::type>::value,
        int
        >::type
    WrapExceptions(Func&& f)
    {
      try { f(); return 0; /* default value */ }
      catch(std::exception) { return -1; }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • decltype:

    template<typename Func>
    auto
    WrapExceptions(Func&& f)
    -> typename std::enable_if<
        std::is_convertible<decltype(f()), int>::value,
        int
        >::type
    {
      try { return f(); }
      catch(std::exception) { return -1; }
    }
    
    template<typename Func>
    auto
    WrapExceptions(Func&& f)
    -> typename std::enable_if<
        std::is_same<void, decltype(f())>::value,
        int
        >::type
    {
      try { f(); return 0; }
      catch(std::exception) { return -1; }
    }
    
    Run Code Online (Sandbox Code Playgroud)