在宏中包装模板函数调用,或者避免专门化void返回

时间:2014-10-02 06:32:08

标签: c++ templates macros

我有以下功能,允许我在出现问题时包装OpenGL命令和日志:

template<typename Res, typename Func, typename... Args>
struct Checker {
    static Res run(const std::string& function_name, Func&& func, Args&&... args) {
        Res result = func(std::forward<Args>(args)...);
        check_and_log_error(function_name);
        return result;
    }
};

template<typename Func, typename... Args>
struct Checker<void, Func, Args...> {
    static void run(const std::string& function_name, Func&& func, Args&&... args) {
        func(std::forward<Args>(args)...);
        check_and_log_error(function_name);
    }
};

template<typename Func>
struct Checker<void, Func> {
    static void run(const std::string& function_name, Func&& func) {
        func();
        check_and_log_error(function_name);
    }
};

}

template<typename Res=void, typename Func, typename... Args>
Res _GLCheck(const std::string& function_name, Func&& func, Args&&... args) {
    GLThreadCheck::check();
    return GLChecker::Checker<Res, Func, Args...>::run(function_name, std::forward<Func>(func), std::forward<Args>(args)...);
}

我想将_GLCheck包装在宏中,以便自动提供函数名参数,例如

#define GLCheck(...) _GLCheck(__func__, __VA_ARGS__)

如果GL调用没有返回值,这可以正常工作,但如果确实如此,那么_GLCheck必须像这样实例化:

program_object_ = _GLCheck<GLuint>(__func__, glCreateProgram);

当我需要指定类似的返回类型时,显然我的宏失败了。有没有办法:

  • 写一个更好的宏来处理这种情况,或者......
  • 避免通过更改模板函数显式定义返回类型?

谢谢!

2 个答案:

答案 0 :(得分:2)

关键是要认识到_GLCheck的模板参数与Func返回的类型相同。因此:

template<typename Func, typename... Args>
auto _GLCheck(const std::string& function_name, Func&& func, Args&&... args)
    -> decltype(func(args...)) {
// ...

首先我尝试使用前面的decltype,但我认为这不可行,所以你会得到上述丑陋。 :)

答案 1 :(得分:-1)

你不需要宏。而是做类似的事情:

ObjectThatWillLogInItsDestructor obj(function_name);
return function_returning_void();