digitalmars.D.learn - 'raii' for structs
- Don Clugston (44/44) Oct 27 2006 I'm trying to get an implementation of floating-point rounding modes.
- David Medlock (14/68) Oct 27 2006 Using inner functions its just as clean IMO.
- BCS (28/46) Oct 27 2006 T With_ROUNDTOZERO(T)( lazy T dg )
- Sean Kelly (13/15) Oct 27 2006 It's not much of an answer, but how about classes constructed in place
- Brad Roberts (8/62) Oct 27 2006 Drop the variables all together.. no need for them here:
I'm trying to get an implementation of floating-point rounding modes.
Normally, you set the rounding mode at the start of a function, and
restore it at exit.
void somefunc()
{
RoundingMode oldmode = setRoundingMode(ROUNDTOZERO);
:
:
:
setRoundingMode(oldmode);
}
It's a classic RAII situation.
In C++, you'd do it as:
struct TemporaryRoundingMode
{
RoundingMode oldmode;
TemporaryRoundingMode(RoundingMode newmode)
{ oldmode = setRoundingMode(newmode); }
~TemporaryRoundingMode() { setRoundingMode(oldmode); }
};
void somefunc()
{
TemporaryRoundingMode tempMode(ROUNDTOZERO);
:
:
}
How can it be done in D? It's only 2 asm instructions, you definitely do
not want memory allocation happening.
Unfortunately you can't do
template TempRoundingMode(int mode)
{
int oldmode = setRoundingMode(mode);
scope(exit) int junk = setRoundingMode(oldmode);
}
void somefunc()
{
mixin TemporaryRoundingMode!(ROUNDTOZERO);
:
:
}
which doesn't require you to name a useless temporary variable; but it
doesn't work, because you can't use scope(exit) in a mixin. And you
couldn't do variables that way, anyway.
Any ideas?
Oct 27 2006
Don Clugston wrote:
I'm trying to get an implementation of floating-point rounding modes.
Normally, you set the rounding mode at the start of a function, and
restore it at exit.
void somefunc()
{
RoundingMode oldmode = setRoundingMode(ROUNDTOZERO);
:
:
:
setRoundingMode(oldmode);
}
It's a classic RAII situation.
In C++, you'd do it as:
struct TemporaryRoundingMode
{
RoundingMode oldmode;
TemporaryRoundingMode(RoundingMode newmode)
{ oldmode = setRoundingMode(newmode); }
~TemporaryRoundingMode() { setRoundingMode(oldmode); }
};
void somefunc()
{
TemporaryRoundingMode tempMode(ROUNDTOZERO);
:
:
}
How can it be done in D? It's only 2 asm instructions, you definitely do
not want memory allocation happening.
Unfortunately you can't do
template TempRoundingMode(int mode)
{
int oldmode = setRoundingMode(mode);
scope(exit) int junk = setRoundingMode(oldmode);
}
void somefunc()
{
mixin TemporaryRoundingMode!(ROUNDTOZERO);
:
:
}
which doesn't require you to name a useless temporary variable; but it
doesn't work, because you can't use scope(exit) in a mixin. And you
couldn't do variables that way, anyway.
Any ideas?
Using inner functions its just as clean IMO.
void withRounding( int mode, void delegate() dg )
{
setRoundingMode( mode);
dg();
restoreRoundingMode();
}
Then to use it:
void foo()
{
withRounding( ROUNDTOZERO, { ..do some stuff here } );
}
-David
Oct 27 2006
David Medlock wrote:
Using inner functions its just as clean IMO.
void withRounding( int mode, void delegate() dg )
{
setRoundingMode( mode);
dg();
restoreRoundingMode();
}
Then to use it:
void foo()
{
withRounding( ROUNDTOZERO, { ..do some stuff here } );
}
-David
T With_ROUNDTOZERO(T)( lazy T dg )
{
RoundingMode oldmode = setRoundingMode(ROUNDTOZERO);
T ret = dg();
setRoundingMode(oldmode);
return ret;
}
void foo()
{
real r = With_ROUNDTOZERO(1+76);
}
all of that should inline (I assume*) to
void foo()
{
RoundingMode oldmode = setRoundingMode(ROUNDTOZERO);
real r = (1+76);
setRoundingMode(oldmode);
}
* does DMD inline lazy arguments when it inlines the function? For that
matter does this get inlined?
void foo()
{
int i;
(){
i=1;
}();
}
Oct 27 2006
Don Clugston wrote:Any ideas?It's not much of an answer, but how about classes constructed in place using alloca :-p I'll admit I sometimes miss stack-based raii types as well. An alternative would be: struct TemporaryRoundingMode { static TemporaryRoundingMode opCall( int mode ) {} void undo() {} } TemporaryRoundingMode m = TemporaryRoundingMode( x ); scope(exit) x.undo(); Still pretty messy though. Sean
Oct 27 2006
Don Clugston wrote:
I'm trying to get an implementation of floating-point rounding modes.
Normally, you set the rounding mode at the start of a function, and
restore it at exit.
void somefunc()
{
RoundingMode oldmode = setRoundingMode(ROUNDTOZERO);
:
:
:
setRoundingMode(oldmode);
}
It's a classic RAII situation.
In C++, you'd do it as:
struct TemporaryRoundingMode
{
RoundingMode oldmode;
TemporaryRoundingMode(RoundingMode newmode)
{ oldmode = setRoundingMode(newmode); }
~TemporaryRoundingMode() { setRoundingMode(oldmode); }
};
void somefunc()
{
TemporaryRoundingMode tempMode(ROUNDTOZERO);
:
:
}
How can it be done in D? It's only 2 asm instructions, you definitely do
not want memory allocation happening.
Unfortunately you can't do
template TempRoundingMode(int mode)
{
int oldmode = setRoundingMode(mode);
scope(exit) int junk = setRoundingMode(oldmode);
}
void somefunc()
{
mixin TemporaryRoundingMode!(ROUNDTOZERO);
:
:
}
which doesn't require you to name a useless temporary variable; but it
doesn't work, because you can't use scope(exit) in a mixin. And you
couldn't do variables that way, anyway.
Any ideas?
Drop the variables all together.. no need for them here:
void somefunc()
{
int oldmode = setRoundingMode(mode);
scope(exit) setRoundingMode(oldMode);
...
}
Oct 27 2006









BCS <BCS pathlink.com> 