我想跟踪我所有的 OpenGL 调用。为此,我有以下宏:
#define EXEC_OPENGL(NAME, ARGUMENTS) debugOpengl(TOSTRING(NAME), [](void) { return NAME ARGUMENTS; })
EXEC_OPENGL(glDoSomething, (1, 2, 3, 4));
而debugOpengl
函数代码类似这样:
void debugOpengl(char const * name, std::function<void ()> const & exec)
{
GLenum err;
exec();
while((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "OpenGL Error: " << name << " " << err << std::endl;
}
}
template <typename Ret>
Ret debugOpengl(char const * name, std::function<Ret ()> const & exec)
{
GLenum err;
auto ret = exec();
while((err = glGetError()) != GL_NO_ERROR)
std::cerr << "OpenGL Error: " << name << " " << err << std::endl;
return ret;
}
这段代码不起作用,因为(至少在 GCC 7 上)当涉及到返回 void 的函数时,宏中定义的 lambda 是无效的(因为 void 值没有被忽略,因为它应该被忽略
)。
我也试过写一个模板仿函数类,但它最终很痛苦而且没有用(我的完美转发未能正确转发文字数字)。
在调用函数之前和之后简单执行某些操作的好方法是什么,假设我可以用宏包装对它的所有调用?
最佳答案
您可能会使用 RAII 来显示错误:
template <typename F>
class Finally {
public:
Finally(F f) : f{f} {}
Finally(const Finally&) = delete;
Finally& operator=(const Finally&) = delete;
~Finally() noexcept {
try {
f();
} catch (...) {
std::cerr << "Exception during stack unwinding" << std::endl;
}
}
private:
F f;
};
template <typename F>
decltype(auto) debugOpengl(const char* name, F&& f)
{
Finally finally{[name](){
GLenum err;
while((err = glGetError()) != GL_NO_ERROR) {
{
std::cerr << "OpenGL Error: " << name << " " << err << std::endl;
}
}};
return f();
}
提供的代码使用 C++17,但可以在 C++11 中完成
关于c++ - 完美包装一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49458477/