Take the following (common) scenario when dealing with, for example, OpenGL:
You have void glUseProgram(GLuint program);
, as well as a host of other functions that all take a GLuint
; but there is no glGetUint
, you're stuck with glGetInteger
.
So, say you have
class Foo() {
public:
Foo::Foo() {
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
}
private:
GLuint program;
void Bar();
};
For literally over 10 years in our project, we've had a similar bit of code and only now, without really changing configuration, the compiler has begun complaining about this particular conversion:
error: implicit conversion changes signedness: 'GLint' (aka 'int') to 'GLuint' (aka 'unsigned int') [-Werror,-Wsign-conversion]
The fix is obviously simple:
class Foo() {
public:
Foo::Foo() {
int _program;
glGetIntegerv(GL_CURRENT_PROGRAM, &_program);
program = static_cast<GLuint>(_program);
}
private:
GLuint program;
void Bar();
};
But the question is, can I do the same in just one step, without having to use a locally-scoped int in the middle of it?
Is there a way to cast when passing arguments to a function that wants a pointer?
I think it is not possible (at least not with a cast).
The problem is that glGetIntegerv
expects a pointer to a signed GLint
(usually an alias for int
), whereas program
is an unsigned integer.
Theoretically you could get rid of the intermediate int _program
, by using a cast in the call, something like:
glGetIntegerv(GL_CURRENT_PROGRAM, static_cast<GLint*>(&program));
But this will not work (as @TedLyngmo demonstrated in a comment below) because you cannot static_cast
from unsigned*
to int*
. reinterpret_cast
can do the job but I would stay away from it as much as possible to avoid UB pitfalls.
Bottom line:
I think your approach using an intermediate variable is a good solution.
However - I would make _program
a GLint
to match the API properly (although it is usually an alias for int
anyway).