c++ - 完美包装一个函数

标签 c++ gcc

我想跟踪我所有的 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/

相关文章:

c++ - 如何为 C++ Visual Studio 2019 指定应用程序图标?

c++ - 仅当变量在 C++ 中可转换时,如何将变量从 int 转换为模板参数

c++ - "rvalue references for *this"是做什么用的?

c++ - QListWidget共享同一个模型

python - 在 Ubuntu 服务器上安装软件包时出现内存不足问题

c++ - WinAPI 窗口消息似乎被插件窃取 - 如何修复?

c - 内联汇编堆栈行为

c - LD_PRELOAD 和外部变量

c++ - 海湾合作委员会 4.1.2 : error: integer constant is too large for ‘long’ type

c - 使用 LD_PRELOAD 重载对共享库的 C 函数的调用