disabling temporaries for a specific class

I

indy2718

Hi,

I've been doing a reoccuring programming error. I'm using a Guard
class (like as in a mutex guard).
The Guard is doing a glBindTexture(new texture) in the constructor,
and then a unbinding BindTexture (original texture) in the
destructor. (see code at the end of this message).

Example:
{
Guard g(x); // constructor called, bind
int i;
// some code
} // destructor of g called, unbind

But sometimes I make a mistake and do:
{
Guard(x); //constructor, destructor calls
// BUG, NOT BOUND
..
}

Is there a way to enforce no temporaries for an object, using any
combination of techniques or consts, or special function calls?

Thanks in advance!
Chris

class BindGuard
{
public:
BindGuard(GlTexture2D * t)
{
int i;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &i);
_oldTex = i;
if (_oldTex != t->texId())
{
glBindTexture(GL_TEXTURE_2D, t->texId());
}
}
~BindGuard()
{
if (_oldTex != _t->texId())
{
glBindTexture(GL_TEXTURE_2D, _oldTex);
}
}
private:
GlTexture2D * _t;
GLuint _oldTex;
};
 
G

Gianni Mariani

Hi,

I've been doing a reoccuring programming error. I'm using a Guard
class (like as in a mutex guard).
The Guard is doing a glBindTexture(new texture) in the constructor,
and then a unbinding BindTexture (original texture) in the
destructor. (see code at the end of this message).

Example:
{
Guard g(x); // constructor called, bind
int i;
// some code
} // destructor of g called, unbind

But sometimes I make a mistake and do:
{
Guard(x); //constructor, destructor calls
// BUG, NOT BOUND
..
}

Is there a way to enforce no temporaries for an object, using any
combination of techniques or consts, or special function calls?
....

Not that I know of.

One suggestion is to not allow access to x other than through the guard.
i.e.

{
Guard g(x);

g.DoStuffToX( blah );
}

or even

{
Guard(x).DoStuffToX( blah );
}

That would mean you would need to stop pushing around raw ogl pointers.
 
A

Adrian Hawryluk

Gianni said:
...

Not that I know of.

One suggestion is to not allow access to x other than through the guard.
i.e.

{
Guard g(x);

g.DoStuffToX( blah );
}

or even

{
Guard(x).DoStuffToX( blah );
}

That would mean you would need to stop pushing around raw ogl pointers.
Yeah, using the Guard as a proxy as Gianni suggested is the best way.
However, you are not guaranteed to have the destructor to be called at
any particular time. I.e. It will be destroyed between the last time
it is used to the end of the enclosing scope. When that will happen
depends on the compiler. To ensure that it is destroyed when you
expect, you must enclose the section with braces and not have other
things in it, just as Gianni's example shows.


Adrian

--
_____________________________________________________________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ My newsgroup writings are licensed under the Creative Commons /
\ Attribution-Noncommercial-Share Alike 3.0 License /
\_____[http://creativecommons.org/licenses/by-nc-sa/3.0/]_____/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
 
G

Gianni Mariani

Adrian said:
Gianni Mariani wrote: ....
Yeah, using the Guard as a proxy as Gianni suggested is the best way.
However, you are not guaranteed to have the destructor to be called at
any particular time. I.e. It will be destroyed between the last time
it is used to the end of the enclosing scope. When that will happen
depends on the compiler. To ensure that it is destroyed when you
expect, you must enclose the section with braces and not have other
things in it, just as Gianni's example shows.

The compiler would be non compliant if it deletes the temporary before
calling DoStuffToX in either case.
 
I

indy2718

The compiler would be non compliant if it deletes the temporary before
calling DoStuffToX in either case.

I made a solution, thanks for your input guys!


#include <iostream>
#include <assert.h>

class NonTemp
{
public:
NonTemp(NonTemp & tmp)
{
assert(&tmp == this);
}
};

class Guard : public NonTemp
{
public:
Guard(NonTemp & t, int i) : NonTemp(t), _i(i)
{
std::cout << "interesting Non Temporary hack my Chris
(e-mail address removed)" << std::endl;
}
~Guard()
{
std::cout << "dest" << std::endl;
}
private:
int _i;
};


int main()
{
Guard g(g, 1);
std::cout << "middle" << std::endl;

// impossible to make a temp!
}
 
G

Gianni Mariani

I made a solution, thanks for your input guys!


#include <iostream>
#include <assert.h>

class NonTemp
{
public:
NonTemp(NonTemp & tmp)
{
assert(&tmp == this);
}
};

class Guard : public NonTemp
{
public:
Guard(NonTemp & t, int i) : NonTemp(t), _i(i)
{
std::cout << "interesting Non Temporary hack my Chris
(e-mail address removed)" << std::endl;
}
~Guard()
{
std::cout << "dest" << std::endl;
}
private:
int _i;
};


int main()
{
Guard g(g, 1);
std::cout << "middle" << std::endl;

// impossible to make a temp!
}

OK - while you're at it, you should also make the copy constructor and
assignment operator private and not implemented.
 
A

Adrian Hawryluk

Gianni said:
The compiler would be non compliant if it deletes the temporary before
calling DoStuffToX in either case.

Ether case? I don't understand.

Calling DoStuffToX() would be the last case it was used, so deletion of
the proxy would happen sometime after the call to the end of the
enclosing scope.


Adrian
--
_____________________________________________________________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ My newsgroup writings are licensed under the Creative Commons /
\ Attribution-Noncommercial-Share Alike 3.0 License /
\_____[http://creativecommons.org/licenses/by-nc-sa/3.0/]_____/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
 
I

indy2718

Yup good idea Gianni, sometimes I don't think of these things.
See what I use it for is like this, I have many functions and I don't
want to keep making helper functions (DoStuffToX), it would complicate
things.

void GlTexture2D::sendToGL(GlBuffer * buffer)
{
BindGuard g(g, this);
GlBuffer::BindBufferGuard bg(bg, buffer);
DEBUG_TIME(1, "sendToGL()");
glTexSubImage2D(target(), 0,
0 /*xoffset*/, 0 /*yoffset*/,
buffer->width(),
buffer->height(),
buffer->dataFormat(),
buffer->dataType(),
BUFFER_OFFSET(0));
}





The compiler would be non compliant if it deletes the temporary before
calling DoStuffToX in either case.

Ether case? I don't understand.

Calling DoStuffToX() would be the last case it was used, so deletion of
the proxy would happen sometime after the call to the end of the
enclosing scope.

Adrian
--
_____________________________________________________________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ My newsgroup writings are licensed under the Creative Commons /
\ Attribution-Noncommercial-Share Alike 3.0 License /
\_____[http://creativecommons.org/licenses/by-nc-sa/3.0/]_____/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top