If you check the OpenGL specification (particularly section 7.6., page 134), you will find that glUniformLocation
is actually specified to return a GLint
, which is a 32-Bit signed integer type. Calling glUniformLocation
is equivalent to a call to glGetProgramResourceLocation
, which has a return type of GLint
as well and is specified to return the value -1
upon error. The comparison of location
to the 0xFFFFFFFF
put there via replacement of the ERROR_VALUE
macro just happens to work in the tutorial code because location
is a GLuint
rather than a GLint
. If glUniformLocation
actually returns -1
there, the -1
will first be implicitly converted to GLuint
. This implicit conversion will follow modulo arithmetic and the -1
will wrap around to become 0xFFFFFFFF
since GLuint
is a 32-Bit unsigned integer type. If location
was of signed type instead, this would not work correctly. As has been pointed out by Nicol Bolas, if you want to compare to some constant to check for success of this function, compare the result to GL_INVALID_INDEX
which is there for exactly this purpose. Contrary to the macro defined in the tutorial code, GL_INVALID_INDEX
is specified to be an unsigned integer of value 0xFFFFFFFF
, which will cause any comparison to work out correctly because of the usual arithmetic conversions…
As others have also noted in the comments above, I would not recommend that you consider the code presented in these tutorials to be representative of good C++. Using macros to define constants in particular is anything but great (see, e.g., here for more on that). We also don't normally use new
to allocate an exception object to throw like here:
throw new exception("error happened");
In general, you'll want to avoid new
in C++ unless you really need it (see, e.g., here for more on that). And if dynamic memory allocation is indeed what you need, then you'd use RAII (smart pointers) to take care of correctly handling the resource allocation…