简体   繁体   English

如何:variadic包装函数捕获输入函数的异常

[英]How to: variadic wrapper function that catches exceptions of input function

I am trying to create a function that I can pass other functions, which will catch any errors, but otherwise simply return the return value of the function. 我正在尝试创建一个函数,我可以传递其他函数,这将捕获任何错误,但否则只返回函数的返回值。 Here's what I've tried: 这是我尝试过的:

#include <iostream>
using namespace std;

int fun(int input)
{
    return input;
}

template <typename F, typename...Args>
static auto HandledCall(const F& function, Args...args)
-> decltype(function(...args))
{
    try
    {
        return function(...args);
    }
    catch(...)
    {
        return NULL;
    }
}

int main() {
    std::cout << HandledCall(fun,1) << std::endl; // this should return 1
    std::cout << HandledCall(fun,-1) << std::endl; // this should return 0      
    return 0;
}

I hope the intention is relatively clear; 我希望意图相对明确; I want HandledCall to be able to receive any kind of function, and return its return value (as long as NULL is implicitly castable to this value in the case of an error). 我希望HandledCall能够接收任何类型的函数,并返回其返回值(只要在出错的情况下NULL可隐式转换为此值)。 However, when I try to compile the above code I get these kinds of errors; 但是,当我尝试编译上面的代码时,我遇到了这些错误;

prog.cpp:10:78: error: expected primary-expression before '...' token static auto HandledCall(const F& function, Args...args) -> decltype(function(...args)) prog.cpp:10:78:错误:在'...'之前预期的primary-expression标记静态自动HandledCall(const F&function,Args ... args) - > decltype(function(... args))

Clearly I'm not doing this variadic templates thing correctly... Any suggestions? 显然我没有正确地做这个可变参数模板的事情......有什么建议吗?

The return type of the function call can be determined using std::result_of . 可以使用std::result_of确定函数调用的返回类型。

template<typename F, typename... Args>
typename std::result_of<F(Args...)>::type
    HandledCall(F&& func, Args&&... args)
{
    using result_type = typename std::result_of<F(Args...)>::type;
    try {
        return std::forward<F>(func)(std::forward<Args>(args)...);
    } catch(...) {
        return result_type();
    }
}

Live demo 现场演示

Something like this? 像这样的东西?

#include <iostream>
using namespace std;

int fun(int input)
{
    return input;
}

template <typename T> struct ReturnType;

template<class Ret, class... Args>
struct ReturnType<Ret(Args...)> 
{
   typedef Ret type;
};


template <typename F, typename...Args>
static auto HandledCall(const F& function, Args...args) -> typename ReturnType<F>::type
{
    try
    {
        return function(args...);
    }
    catch(...)
    {
        return typename ReturnType<F>::type{0};
    }
}

int main() {
    std::cout << HandledCall(fun,1) << std::endl; // this should return 1
    std::cout << HandledCall(fun,-1) << std::endl; // this should return 0      
    return 0;
}

Update 更新

An improved version of HandledCall (Thanks to Mankarse): HandledCall的改进版本(感谢Mankarse):

template <typename F, typename...Args>
static auto HandledCall(const F& function, Args&&...args) -> typename ReturnType<F>::type
{
    try
    {
        return function(std::forward<Args>(args)...);
    }
    catch(...)
    {
        return typename ReturnType<F>::type{0};
    }
}

Here is a version based on the solution presented by @Praetorian but which also works for functions with a void return type. 这是一个基于@Praetorian提供的解决方案的版本,但也适用于具有void返回类型的函数。 The reason the other answers could not handle this case is the explicit instantiation of an object of type void . 其他答案无法处理这种情况的原因是void类型对象的显式实例化。

template<typename T> 
T default_value(){return {};}

template<>
void default_value<void>(){}

template<typename F, typename... Args>
typename std::result_of<F(Args...)>::type
  HandledCall(F&& func, Args&&... args)
{
  try {
      return std::forward<F>(func)(std::forward<Args>(args)...);
  } catch(...) {
      return default_value<typename std::result_of<F(Args...)>::type>();
  }
}

The reason this works is because the standard allows explicitly returning void values in a function with void return type. 这样做的原因是因为标准允许在具有void返回类型的函数中显式返回void值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM