Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
October 27, 2006 'raii' for structs | ||||
---|---|---|---|---|
| ||||
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? |
October 27, 2006 Re: 'raii' for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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
|
October 27, 2006 Re: 'raii' for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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
|
October 27, 2006 Re: 'raii' for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | 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;
}();
}
|
October 27, 2006 Re: 'raii' for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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);
...
}
|
Copyright © 1999-2021 by the D Language Foundation