完美包装功能

时间:2018-03-23 21:25:45

标签: 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 value not ignored as it ought to be)。

我也尝试过写一个模板仿函数类,但它最终是一个痛苦而且没有用(我的完美转发无法正确转发文字数字)。

什么是在调用函数之前和之后简单执行某些东西的好方法,假设我可以用宏包装所有调用它?

2 个答案:

答案 0 :(得分:1)

您可以使用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中完成

答案 1 :(得分:0)

这是一个GCC错误,since fixed:如果lambda’s return type返回该类型的表达式,则deduced as voidqlot