This is going to be a self-answered question that I'm putting on SO in the hope that it will spare other programmers the try-and-error that I required to reach a solution.
Most of the OpenGL API calls do not return a value. With C++11 perfect forwarding, it would be easy to write an error-checking wrapper function template and variadic macro such as this:
template <typename F, typename ...Args>
void call(
const char *text,
int line,
const char *file,
F && f, Args &&... args
)
{
std::forward<F>(f)(std::forward<Args>(args)...);
auto err = glGetError();
if (err != 0) _throw_error(text, err, line, file);
}
#define GL(fn, ...) call(#fn, __LINE__, __FILE__, gl##fn, __VA_ARGS__)
This works and allows calls to be written like this:
GL(Viewport, 0, 0, 1920, 1080);
However, some OpenGL functions do return a value, making it necessary for the wrapper function to store the return value in a temporary variable before checking for errors. The wrapper function template for calls with return values could be written like this:
template <typename F, typename ...Args>
auto call(
const char *text,
int line,
const char *file,
F && f, Args &&... args
)
{
auto && res = std::forward<F>(f)(std::forward<Args>(args)...);
auto err = glGetError();
if (err != 0) _throw_error(text, err, line, file);
return res;
}
(The same macro can be used to call this form.)
The problem is that it is not possible to define both of the above function templates, because for all API calls with void return type, both templates will match, leading to an "ambiguous call to overloaded function" error (Visual C++).
It would be possible, of course, to define separate macros for the two forms, but that would not be elegant. GL is the natural, obvious and correct choice for the name of the wrapper macro, and any additional macro (such as GLR) would appear ugly and be difficult to remember.
Aucun commentaire:
Enregistrer un commentaire