Macros are fine. Templates are fine. Pretty much whatever it works is fine.
The example is OpenGL; but the technique is C++ specific and relies on no knowledge of OpenGL.
Precise problem:
I want an expression E; where I do not have to specify a unique name; such that a constructor is called where E is defined, and a destructor is called where the block E is in ends.
For example, consider:
class GlTranslate {
GLTranslate(float x, float y, float z); {
glPushMatrix();
glTranslatef(x, y, z);
}
~GlTranslate() { glPopMatrix(); }
};
Manual solution:
{
GlTranslate foo(1.0, 0.0, 0.0); // I had to give it a name
.....
} // auto popmatrix
Now, I have this not only for glTranslate, but lots of other PushAttrib/PopAttrib calls too. I would prefer not to have to come up with a unique name for each var. Is there some trick involving macros templates ... or something else that will automatically create a variable who's constructor is called at point of definition; and destructor called at end of block?
Thanks!
I think it's now possible to do something like this:
then in the code
Obviously, C++11 is needed
I would not do this personally but just come up with unique names. But if you want to do it, one way is to use a combination of
if
andfor
:You can use it like
Each of those names are in separate scopes and won't conflict. The inner names hide the outer names. The expressions in the
if
andfor
loops are constant and should be easily optimized by the compiler.If you really want to pass an expression, you can use the ScopedGuard trick (see Most Important
const
), but it will need some more work to write it. But the nice side is, that we can get rid of thefor
loop, and let our object evaluate tofalse
:You then provide the proper
enter
andleave
functions:Now you can write it entirely without a name on the user side:
If you want to pass multiple expressions at once, it's a bit more tricky, but you can write an expression template that acts on
operator,
to collect all expressions into ascont
.You need to inherit the RAII object from
scoped_obj<Class>
like the following showsAll of these involve no virtual functions, and the functions involved are transparent to the compiler. In fact, with the above
GLTranslate
changed to add a single integer to a global variable and when leaving subtracting it again, and the below definedGLTranslateE
, i did a test:In fact, GCC at optimization level
-O2
outputs this:I wouldn't have expected that, it optimized quite well!
If your compiler supports
__COUNTER__
(it probably does), you could try:For