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 } ); } -DavidT 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