Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?_C++_Templates_Error Handling - Fatal编程技术网

C++ 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?

C++ 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?,c++,templates,error-handling,C++,Templates,Error Handling,我想包装一些对现有C库的函数调用,它调用函数,检查是否设置了错误条件,然后返回函数的值(如果有)。(特别是,这适用于OpenGl,但也适用于遗留的C函数。)函数可能返回void这一事实使这一点变得复杂,需要单独处理;我想抛出异常,这阻止我在保护对象的析构函数超出范围时进行检查 以下代码基本上起作用: void check_for_error() { // check and handle legacy error messages // if (errno != 0) // if (glGetE

我想包装一些对现有C库的函数调用,它调用函数,检查是否设置了错误条件,然后返回函数的值(如果有)。(特别是,这适用于OpenGl,但也适用于遗留的C函数。)函数可能返回void这一事实使这一点变得复杂,需要单独处理;我想抛出异常,这阻止我在保护对象的析构函数超出范围时进行检查

以下代码基本上起作用:

void check_for_error() {
// check and handle legacy error messages
// if (errno != 0)
// if (glGetError() != GL_NO_ERROR)
//   throw std::runtime_error{"suitable error message"};
}

template <class R, class... Args>
using RvalFunc = R(*)(Args...);

// specialisation for funcs which return a value
template <class R, class... Args>
R exec_and_check(RvalFunc<R, Args...> func, Args... args) {
  R rval = func(std::forward<Args>(args)...);
  check_for_error();
  return rval;
}

template <class... Args>
using VoidFunc = void(*)(Args...);

// specialisation for funcs which return void - don't store rval
template <class... Args>
void exec_and_check(VoidFunc<Args...> func, Args... args) {
  func(std::forward<Args>(args)...);
  check_for_error();
}
…而不是

glBindBuffer(target,name);
check_for_error();
FILE *pf = fopen("filename.txt", "rb");
check_for_error();
…检查可能会漏掉,这会使代码混乱。我希望
R exec_和_检查(RvalFunc,Args…Args)
包含转发的通用参考(即
Args&&…Args
),但这种替换会导致编译错误-Clang给出
注意:忽略候选模板:例如,推断参数“Args”(vs.)的冲突类型


如何修改此代码以接受通用引用?或者我遗漏了什么,还有更好的方法来检查遗留代码吗?

问题是您有两个模板函数,就编译器而言,它们只在返回类型上有所不同。要解决此问题,可以按如下方式使用SFINAE:

// specialisation for funcs which return a value
template <class R, class... Args>
std::enable_if_t<!std::is_void<R>::value, R>
exec_and_check(RvalFunc<R, Args...> func, Args... args) {
  R rval = func(std::forward<Args>(args)...);
  check_for_error();
  return rval;
}
//返回值的函数的专门化
模板
std::如果\u t::value,R>
执行和检查(RvalFunc func,Args…Args){

R rval=func(std::forward)

恐怕这不是问题所在-RvalFunc和VoidFunc是函数参数,Clang能够解决它们。我遇到的问题是我无法编写
exec_和_check(RvalFunc,Args&&…Args)
为了获得完美的转发,这意味着传递给这些模板的某些参数无法按预期工作。不过,谢谢。很有趣。如果没有建议的更改,gcc无法解决这些问题,我认为这就是问题所在。另请参阅(请注意两个模板中的
参数&&
),这是您想要的吗?
// specialisation for funcs which return a value
template <class R, class... Args>
std::enable_if_t<!std::is_void<R>::value, R>
exec_and_check(RvalFunc<R, Args...> func, Args... args) {
  R rval = func(std::forward<Args>(args)...);
  check_for_error();
  return rval;
}