我正在尝试创建一个函数,我可以传递其他函数,这将捕获任何错误,但否则只返回函数的返回值。以下是我尝试过的内容:
#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;
}
我希望意图相对明确;我希望HandledCall
能够接收任何类型的函数,并返回其返回值(只要NULL
在出现错误时可以隐式转换为此值)。但是,当我尝试编译上面的代码时,我遇到了这些错误;
prog.cpp:10:78:错误:在'...'标记之前预期的primary-expression static auto HandledCall(const F&amp; function,Args ... args) - &gt; decltype(函数(...参数))
显然,我没有正确地做这个可变参数模板的事情......有什么建议吗?
答案 0 :(得分:4)
可以使用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();
}
}
答案 1 :(得分:3)
这样的东西?
#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;
}
更新
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};
}
}
答案 2 :(得分:1)
这是一个基于@Praetorian提供的解决方案的版本,但也适用于具有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>();
}
}
这样做的原因是因为标准允许在具有void返回类型的函数中显式返回void值。