在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?
How do I use perfect forwarding when writing template functions that wrap existing functions and check for errors?
我想将许多函数调用包装到现有的 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();
}
用法示例:
exec_and_check(glBindBuffer, target, name);
FILE *pf = exec_and_check(fopen, "filename.txt", "rb");
。而不是...
glBindBuffer(target,name);
check_for_error();
FILE *pf = fopen("filename.txt", "rb");
check_for_error();
。检查可能会丢失的地方,以及使代码混乱的地方。 我希望R exec_and_check(RvalFunc<R, Args...> func, Args... args)
包含用于转发的通用参考(即。Args&&... args
(,但该替换会导致编译错误 - Clang给出了note: candidate template ignored: deduced conflicting types for parameter 'Args' (<int, int> vs. <const int &, const int &>)
为例。
如何修改此代码以接受通用引用? 或者我错过了一些东西,并且有一种更好的方法来错误检查遗留代码?
问题是你有两个模板函数,就编译器而言,它们仅在返回类型上有所不同。 要解决此问题,您可以按如下方式使用 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;
}
这解决了问题(通过防止上述模板函数在void
时匹配R
(。
现场演示
相关文章:
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 在c++构造函数中使用随机字符串生成器
- 如何在C++中的同一函数中使用字符串和双精度
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- 对函数 PlaySound 使用字符串变量
- 编写一个函数以使用 n 百分比的 CPU 使用率
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- C ++:在构造函数中使用参数包?
- c++ 在非类函数中使用类变量
- 函数如何使用引用返回所需的数字?
- 在 void 函数中使用 #include 变量C++
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 在构造函数中使用 lambda 的 C++ 类
- (SFML)按下键时,播放器构造函数未使用正确的动画进行更新
- 什么是自定义比较器以及如何在 C++ 的排序函数中使用它?
- 在类构造函数中使用结构变量
- 为什么我不能在 constexpr lambda 函数中使用 std::tuple
- 在定义的函数中使用常量时出错
- 如何在构造函数中使用初始值设定项设置具有相同值的 2d 数组?
- 在构造函数中使用可变参数初始化 std::tuple