is RAII really always the better choice ?

21 views
Skip to first unread message

Roshan Naik

unread,
May 4, 2005, 6:34:38 AM5/4/05
to
I know that using the finally block (in Java or C#) to dispose resources is
considered inferiror to RAII.
However I recently came accross a little C++ example that used some
compiler's __finally language extension
that made me rethink there might be some value in finally...sometimes.

The code was something to this effect (roughly)....

mouse.setCursor(HOUR_GLASS); // change state
try {
doSomeTimeConsumingWork( );
}
__finally { // non standard extension
mouse.setCursor(NORMAL_POINTER); //reset state
}


Clearly there is no resrouce acquisistion/disposal going on here. Just
change some state , do some work, and then reset the state.
And here RAII can be put to work (and ScopeGuard comes to mind), but it is
not at all natural to use destructors for doing such things. That
immediately feels more like a hack.... and hides the intent of the code
somewhere behind the scenes.

Also it seems useful in cases where you want to guarantee the restoration of
an invariant.

-Roshan


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Bronek Kozicki

unread,
May 4, 2005, 7:57:24 AM5/4/05
to
Roshan Naik <som...@somehwere.com> wrote:
> However I recently came accross a little C++ example that used some
> compiler's __finally language extension

Microsoft Visual C++ family of compilers provides exception handling in
C (as opposed to C++) through compiler extensions and OS facilities
called Structured Exception Handling (SEH). These extensions are not
disabled when compiling C++ code. Nevertheless, they do not have much
use in C++, as documentation for MSVC clearly states. But for C code,
these are as much valuable as "try ... finally" for Java. I suppose that
you found this code in C project or project (partly) ported from C, or
code written by someone accustomed to this (quite old) exception
handling mechanism and/or not familiar with RAII.

Having said that, there are situations when this mechanism has good use
also in C++ code directed on Windows platform - that is because some OS
specific functions might throw SEH exception in well-defined conditions
(examples in documentation of InitializeCriticalSection, MapViewOfFile
etc).

> Clearly there is no resrouce acquisistion/disposal going on here. Just
> change some state , do some work, and then reset the state.
> And here RAII can be put to work (and ScopeGuard comes to mind), but
> it is not at all natural to use destructors for doing such things.

> That immediately feels more like a hack.... and hides the intent of
> the code somewhere behind the scenes.

RAII would not be hack at all, at least for me. You acquire resource
(cursor) and then release it (reset cursor to normal state) when you are
done.


B.

Nemanja Trifunovic

unread,
May 4, 2005, 10:09:54 AM5/4/05
to
> The code was something to this effect (roughly)....

mouse.setCursor(HOUR_GLASS); // change state
try {
doSomeTimeConsumingWork( );
}
__finally { // non standard extension

mouse.setCursor(NORMAL_POINTER­); //reset state
}

Funny you mention this as an example. In MFC, there is a class called
CWaitCursor that uses RAII exactly for that puropse.

j_ri...@gmx.de

unread,
May 4, 2005, 11:09:25 AM5/4/05
to
Roshan Naik schrieb:

> The code was something to this effect (roughly)....
>
> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>
>
> Clearly there is no resrouce acquisistion/disposal going on here.
Just
> change some state , do some work, and then reset the state.
> And here RAII can be put to work (and ScopeGuard comes to mind), but
it is
> not at all natural to use destructors for doing such things.

I think this is a very good example to use an object. It has several
advantages. You write only 1 line instead of 6. The code becomes
something like this:

{
HourClassCursor hcc;
doSomeTimeConsumingWork();
}

And not to forget. After you've inserted a lot of your code snipets in
different functions you later discover that this doesn't nest. And now
you have to find all places and change them to increment/decrement a
counter and only switch the cursor when leaving/reaching 0. With RAII
you only have to adjust the constructor/destructor to fix your code.
Okay, this would also be true if you use functions to do the actual
counting/switching. But if you are not careful, you end up having some
unmatched function calls and your mouse cursor always stays like a hour
glass. This effect is impossible with RAII.


Joerg

Joshua Lehrer

unread,
May 4, 2005, 11:08:34 AM5/4/05
to

"Roshan Naik" <som...@somehwere.com> wrote in message
news:J50ee.5377$HL2....@newsread3.news.pas.earthlink.net...

> I know that using the finally block (in Java or C#) to dispose resources
is
> considered inferiror to RAII.
> However I recently came accross a little C++ example that used some
> compiler's __finally language extension
> that made me rethink there might be some value in finally...sometimes.
>
> The code was something to this effect (roughly)....
>
> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>
>

I find that code much harder to follow than:

const cursort old_cursor = mouse.setCursor(HOUR_GLASS);
ON_BLOCK_EXIT_OBJ(mouse,&mouse_t::setCursor,old_cursor);

this is 2 lines, instead of 7.

You can even do it in a single line, if that floats your boat, if set
setCursor returns the old cursor:

ON_BLOCK_EXIT_OBJ(mouse,&mouse_t::setCursor,mouse.setCursor(HOUR_GLASS));

Both of these code snippets are far superior to the try/finally in
readability. Also, generally a "finally" block gets run no matter what,
even if "doSomeTimeConsumingWork" were to throw and exception. But, if an
exception were thrown, how do you know that you can reliably put the cursor
back? At least with RAII, if the exception is caught, the resource is
guaranteed to be restored (object destructor is called). If the exception
is not caught, it is undefined whether it will run, or not. On my platform,
it currently does not.


joshua lehrer
factset research systems
NYSE:FDS

david...@ed.tadpole.com

unread,
May 4, 2005, 8:01:38 PM5/4/05
to

Joshua Lehrer wrote:
<snip>

> Both of these code snippets are far superior to the try/finally in
> readability.
<snip>

This unqualified assertion makes it sound as if this is objectively
true when it is subjective. I find a finally clause far more intuitive
and readable than a side-effect of a destructor for an object defined
at the top of a (possibly lengthy) function.

Cheers,

Dave

Andrei Alexandrescu (See Website For Email)

unread,
May 4, 2005, 8:16:32 PM5/4/05
to
Roshan Naik wrote:
> I know that using the finally block (in Java or C#) to dispose resources is
> considered inferiror to RAII.
> However I recently came accross a little C++ example that used some
> compiler's __finally language extension
> that made me rethink there might be some value in finally...sometimes.
>
> The code was something to this effect (roughly)....
>
> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>
>
> Clearly there is no resrouce acquisistion/disposal going on here. Just
> change some state , do some work, and then reset the state.
> And here RAII can be put to work (and ScopeGuard comes to mind), but it is
> not at all natural to use destructors for doing such things. That
> immediately feels more like a hack.... and hides the intent of the code
> somewhere behind the scenes.

The problem with the code above is that the two logically paired actions
are spread across the code. It's the exact kind of example that
ScopeGuard puts to shame, because with ScopeGuard (and ON_BLOCK_EXIT)
you can put a current and future action together, as a single unit.


Andrei

James Kanze

unread,
May 4, 2005, 8:15:32 PM5/4/05
to
Bronek Kozicki wrote:
> Roshan Naik <som...@somehwere.com> wrote:

[...]


>>Clearly there is no resrouce acquisistion/disposal going on
>>here. Just change some state , do some work, and then reset
>>the state. And here RAII can be put to work (and ScopeGuard
>>comes to mind), but it is not at all natural to use
>>destructors for doing such things.

>>That immediately feels more like a hack.... and hides the
>>intent of the code somewhere behind the scenes.

> RAII would not be hack at all, at least for me. You acquire
> resource (cursor) and then release it (reset cursor to normal
> state) when you are done.

"'Tis but thy name that is my enemy." (Romeo and Juliette,
II.2, l.38). There are no resources involved, and resource
acquision isn't being used for initialization. But what is
commonly called RAII is certainly what is called for. It sure
smells sweet, even if we don't call it a rose.

IMHO, the only reason that it feels like a hack is because the
pattern is so poorly named. I regularly use RAII for things
where no resources are involved, and just as often for cases
where the resource acquisition does not take place in the
initialization.

--
James Kanze mailto: james...@free.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Walter

unread,
May 4, 2005, 8:27:43 PM5/4/05
to

"Roshan Naik" <som...@somehwere.com> wrote in message
news:J50ee.5377$HL2....@newsread3.news.pas.earthlink.net...
> I know that using the finally block (in Java or C#) to dispose resources
is
> considered inferiror to RAII.
> However I recently came accross a little C++ example that used some
> compiler's __finally language extension
> that made me rethink there might be some value in finally...sometimes.

Using a finally block is helpful when:

1) the cleanup code needs to access local variables in the function

2) it's a one use issue; i.e. when making a class just for one use would
wind up cluttering the code

For example, suppose we want to open a file, do some processing, then make
sure it gets closed:

void foo()
{
...
FILE *fp = fopen( ... );
if (fp)
try
{
....
}
finally
{
fclose(fp);
}
}

Yes, I could wrap fp in a class with a destructor, and I would if I was
going to use it more than once. But if it's just a one shot deal, the above
is simpler and more direct. Ideally, the language should support both RAII
objects and try-finally.

James Kanze

unread,
May 5, 2005, 8:52:40 AM5/5/05
to
Walter wrote:
> "Roshan Naik" <som...@somehwere.com> wrote in message
> news:J50ee.5377$HL2....@newsread3.news.pas.earthlink.net...

>>I know that using the finally block (in Java or C#) to dispose
>>resources is considered inferiror to RAII. However I recently
>>came accross a little C++ example that used some compiler's
>>__finally language extension that made me rethink there might
>>be some value in finally...sometimes.

> Using a finally block is helpful when:

> 1) the cleanup code needs to access local variables in the function

That is (at least in my mind) one of the major motivations for
"lambda classes" (or whatever you want to call them). While
there's been a great deal of discussion concerning the possible
syntax and the various uses, I think that all of the suggestions
have in common an ability to locally define a class or a
function in which you can access local variables.

Given such a class, it's pretty trivial to define something
like:

cleanup { some code .. } ;

as a contraction for an instance of a lambda class with a
destructor consisting of the code in the {...}.

> 2) it's a one use issue; i.e. when making a class just for one
> use would wind up cluttering the code

Agreed. On the other hand, in current C++, not making the class
means duplicating the code.

IMHO, the functionality is definitly useful. The question is
just how to achieve it. Personally, I find that something like
the cleanup verb, above, fits better into the overall scheme of
things in C++.

> For example, suppose we want to open a file, do some
> processing, then make sure it gets closed:

> void foo()
> {
> ...
> FILE *fp = fopen( ... );
> if (fp)
> try
> {
> ....
> }
> finally
> {
> fclose(fp);
> }
> }

> Yes, I could wrap fp in a class with a destructor, and I would
> if I was going to use it more than once. But if it's just a
> one shot deal, the above is simpler and more direct. Ideally,
> the language should support both RAII objects and try-finally.

The problem with all such examples is that they take an obvious
and frequent case. One so obvious and frequent that it
justifies a library class to handle it. But I totally agree in
principal; there will always be one-of cases where the explicit
class is just so much verbage. On the other hand, I rather
prefer:


FILE *fp = fopen( ... ) ;

if ( fp != NULL ) {
cleanup { fclose( fp ) ; }
}

Except that it's still a bad example, since in the normal case,
I'd certainly want to handle errors in the fclose, and would
thus naturally write something along the lines of:

if ( fp != NULL ) {
try {
...
if ( fclose( fp ) != 0 ) {
// handle errors...
}
} catch ( ... ) {
fclose( fp ) ; // can't do much about errors here,
// but it doesn't matter, the
// operation is hosed anyway.
throw ;
}
}

(Except, of course, I'd actually be using fstream, so the
try/catch would be unnecessary. Unless I was outputting and
wanted to delete the corrupted file I'd just generated.)

--
James Kanze mailto: james...@free.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Roland Pibinger

unread,
May 5, 2005, 8:53:03 AM5/5/05
to
On 4 May 2005 20:16:32 -0400, "Andrei Alexandrescu (See Website For

Email)" <SeeWebsit...@moderncppdesign.com> wrote:
>
>The problem with the code above is that the two logically paired actions
>are spread across the code. It's the exact kind of example that
>ScopeGuard puts to shame, because with ScopeGuard (and ON_BLOCK_EXIT)
>you can put a current and future action together, as a single unit.

Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost) equivalent to
try/finally. The 'finally clause' is merely written before the
statements, not below. I case of ScopeGuard the user must even call a
second logically paired action (confusingly called 'dismiss'). In both
cases (try/finally and ScopeGuard) it's the user's responsibility to
set up the release of a resource. In both cases resource management is
not encapsulated.

Best regards,
Roland Pibinger

Joshua Lehrer

unread,
May 5, 2005, 12:48:10 PM5/5/05
to

<david...@ed.tadpole.com> wrote in message
news:1115224165....@o13g2000cwo.googlegroups.com...

>
> Joshua Lehrer wrote:
> <snip>
> > Both of these code snippets are far superior to the try/finally in
> > readability.
> <snip>
>
> This unqualified assertion makes it sound as if this is objectively
> true when it is subjective. I find a finally clause far more intuitive
> and readable than a side-effect of a destructor for an object defined
> at the top of a (possibly lengthy) function.
>
> Cheers,
>
> Dave
>

As you point out, in a lengthy function, try/finally puts the "undo"
operation is far away from your "do" operation. If you change your
operation at the top, you may forget that you need to scroll all the way
down to the finally block to fix the undo operation. Sure, in a SIMPLE
example such as:

do();
try {
} finally {
undo();
}

it is obvious. But, consider when there is lots of code between try and
finally. If you keep related operations next to eachother, there is less
chance that you will make a mistake later on down the road when modifying
the code.

Also, someone who looks at your code won't need to ask if you are cleaning
up your resource, as the resource is acquired and disposition is set-up on
the very next line. With try/finally one needs to scroll way down (given a
large function) to see if you are releasing the resource properly, or at
all.

joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Joshua Lehrer

unread,
May 5, 2005, 12:47:48 PM5/5/05
to

"Roland Pibinger" <rpb...@yahoo.com> wrote in message
news:4279ea1...@news.utanet.at...

> On 4 May 2005 20:16:32 -0400, "Andrei Alexandrescu (See Website For
> Email)" <SeeWebsit...@moderncppdesign.com> wrote:
> >
> In both
> cases (try/finally and ScopeGuard) it's the user's responsibility to
> set up the release of a resource. In both cases resource management is
> not encapsulated.
>
> Best regards,
> Roland Pibinger
>

This is correct. However, people will not take the time to write custom
classes, so, scopeguard is a compromise.

joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Hillel Y. Sims

unread,
May 5, 2005, 12:52:04 PM5/5/05
to

"Roland Pibinger" <rpb...@yahoo.com> wrote in message
news:4279ea1...@news.utanet.at...

> On 4 May 2005 20:16:32 -0400, "Andrei Alexandrescu (See Website
For
> Email)" <SeeWebsit...@moderncppdesign.com> wrote:
> >
> >The problem with the code above is that the two logically
paired actions
> >are spread across the code. It's the exact kind of example
that
> >ScopeGuard puts to shame, because with ScopeGuard (and
ON_BLOCK_EXIT)
> >you can put a current and future action together, as a single
unit.
>
> Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost) equivalent
to
> try/finally. The 'finally clause' is merely written before the
> statements, not below.

I have created a small extension to ScopeGuard that we have been
using locally for some time, called "finally" (the implementation
details shall be left to the imagination of the reader for the
moment). The following type of code compiles and executes
perfectly, using no non-standard language extensions. "finally"
is in extensive production use throughout our system.

using namespace boost;

mouse.setCursor(HOUR_GLASS);
finally(bind(&MouseType::setCursor, ref(mouse), NORMAL_POINTER))
{
doSomeTimeConsumingWork();
}

This provides exactly the same semantics as ON_BLOCK_EXIT, but I
like the stylistic look and feel better (esp. consistent use of
bind() to avoid the need for ON_BLOCK_EXIT vs.
ON_BLOCK_EXIT_OBJ).

I also have a similar wrapper for named ScopeGuards that can be
.Dismiss()ed, which I call GuardRegion - GuardRegion(name,
funcobj) { stuff(); name.Dismiss(); }

"Roshan Naik" <som...@somehwere.com> wrote in message
news:J50ee.5377$HL2....@newsread3.news.pas.earthlink.net...
>

> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>

I feel that the RAII-based prefix form of finally() offers
benefits over this form of exception-handling - aside from
portability and potential reduction in duplication of code, there
are aspects of system debugging (in cases of abnormal termination
due to unhandled exceptions) which are often complicated by the
presence of such __finally constructs. RAII-based cleanup
handlers do not usually encounter the same difficulties. OpenVMS
(on which win32's SEH exception-handling mechanism was based) has
a similar construct called FINALLY - we have long discouraged the
use of FINALLY by developers in favor of RAII-style exception
handling, due to these issues.


--
Hillel Y. Sims
hsims AT factset.com

Joshua Lehrer

unread,
May 6, 2005, 3:53:14 AM5/6/05
to
Andrei -

I have a suggestion for a way to improve ScopeGuard and bring it's interface
more in line with boost::bind.

Using scopeguard's native object creation factories are superior to mixing
scopeguard and boost::bind because boost::bind requires dynamic memory
allocation and a virtual function call, scopeguard does not. Thus, I'd
prefer to use ScopeGuard's factory methods, rather than a mix of ScopeGuard
and boost::bind.


However, ScopeGuard strays from boost::bind in two ways:

1] boost::bind does not require special "OBJ" macros; ScopeGuard does.

2] boost::bind passes the method pointer first, then the "this" pointer,
then the arguments. ScopeGuard passes the object by reference, then the
method pointer, then the arguments by copy. This mixing of reference and
copy confuses people.


Both of these can be solved by adding additional object factory methods to
ScopeGuard.h. Here, I supply the two-argument versions, but a similar
pattern can easily be followed for the zero-argument and one-argument
versions:

template <typename Ret, typename P1, typename P2, class Obj1, class Obj2>
inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1,P2),P1,P2>
MakeScopeGuard(Ret(Obj2::*memFun)(P1,P2), Obj1 *obj, P1 p1, P2 p2)
{
return
ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1,P2),P1,P2>::MakeObjScopeGuard(*obj,m
emFun, p1,p2);
}

template <typename Ret, typename P1, typename P2, class Obj1, class Obj2>
inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1,P2)const,P1,P2>
MakeScopeGuard(Ret(Obj2::*memFun)(P1,P2)const, Obj1 *obj, P1 p1, P2 p2)
{
return
ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1,P2)const,P1,P2>::MakeObjScopeGuard(*
obj,memFun,p1,p2);
}


Usage:

old: ON_BLOCK_EXIT_OBJ(s,&string::clear);
new: ON_BLOCK_EXIT(&string::clear,&s);


Implementation details:

Two functions need to be supplied, one for const-members and one for
non-const members.

Also, these functions are templated both on the object pointer type supplied
(Obj1) AND on the method pointer's object-type (Obj2). This allows you to
pass in a pointer to a subclass, while passing in a pointer to a method on a
base. While the compiler normally would do this cast automatically, it will
not, in this case, as the other non-object templated factory methods would
be better matches without any casting, and would fail to compile.

Each factory method remains a simple cover function to creating an
ObjScopeGuardImplN. The factory method's sole purpose remains doing the
template argument deduction.


I have added these factory methods to my local version of ScopeGuard, and
thought I would share with the group.


joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Andrei Alexandrescu

unread,
May 6, 2005, 4:00:52 AM5/6/05
to
Hillel Y. Sims wrote:
> using namespace boost;
>
> mouse.setCursor(HOUR_GLASS);
> finally(bind(&MouseType::setCursor, ref(mouse), NORMAL_POINTER))
> {
> doSomeTimeConsumingWork();
> }
>
> This provides exactly the same semantics as ON_BLOCK_EXIT, but I
> like the stylistic look and feel better (esp. consistent use of
> bind() to avoid the need for ON_BLOCK_EXIT vs.
> ON_BLOCK_EXIT_OBJ).

That looks great, but why do you need ref(mouse) as opposed to mouse? I
think the default should be reference, and only if you need a copy you'd
say value(mouse). Or does that come with the generality of the construct?


Andrei

Hillel Y. Sims

unread,
May 6, 2005, 4:05:04 AM5/6/05
to

"James Kanze" <ka...@none.news.free.fr> wrote in message
news:4279ef04$0$315$626a...@news.free.fr...

>
>
> FILE *fp = fopen( ... ) ;
> if ( fp != NULL ) {
> cleanup { fclose( fp ) ; }
> }

What do you think about the following?

FILE* fp = fopen("xyz","r");
if (fp != 0) {
finally(bind<int>(fclose, fp)) {
process_file(fp);
}
}

I've just copy/pasted that from a source file that compiled and
linked successfully.

>
> Except that it's still a bad example, since in the normal case,
> I'd certainly want to handle errors in the fclose, and would
> thus naturally write something along the lines of:
>
> if ( fp != NULL ) {
> try {
> ...
> if ( fclose( fp ) != 0 ) {
> // handle errors...
> }
> } catch ( ... ) {
> fclose( fp ) ; // can't do much about errors
here,
> // but it doesn't matter, the
> // operation is hosed anyway.
> throw ;
> }
> }
>
> (Except, of course, I'd actually be using fstream, so the
> try/catch would be unnecessary. Unless I was outputting and
> wanted to delete the corrupted file I'd just generated.)
>

What if the filename itself has also been corrupted when you make
that call to remove(filename)? Besides, isn't fclose() a no-throw
operation?


--
Hillel Y. Sims
hsims AT factset.com

Andrei Alexandrescu

unread,
May 6, 2005, 4:05:26 AM5/6/05
to
Roland Pibinger wrote:
> On 4 May 2005 20:16:32 -0400, "Andrei Alexandrescu (See Website For
> Email)" <SeeWebsit...@moderncppdesign.com> wrote:
>
>>The problem with the code above is that the two logically paired actions
>>are spread across the code. It's the exact kind of example that
>>ScopeGuard puts to shame, because with ScopeGuard (and ON_BLOCK_EXIT)
>>you can put a current and future action together, as a single unit.
>
>
> Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost) equivalent to
> try/finally. The 'finally clause' is merely written before the
> statements, not below.

I think spreading the code gratuitously is an important detail. For
small idioms, I've noticed that things like where the logically
consistent pieces are, and what the level of syntactic baroqueness is,
do matter a lot.

> I case of ScopeGuard the user must even call a
> second logically paired action (confusingly called 'dismiss').

Nonono. "Suggestively" called dismiss. :o)

Note that try/finally doesn't have any dismissing mechanism, so it's
unfair to mention that as a disadvantage of ScopeGuard. For try/finally,
the user must maintain their own flag. (They might call it 'dismissed'.
:o)) So try/finally is more of a poor man's version of ON_BLOCK_EXIT
(with the disadvantage that it spreads away code that should be
together, but with the advantage that it allows arbitrary code in the
finally block), which in turn is a particular use of the dismissible
ScopeGuard.

> In both
> cases (try/finally and ScopeGuard) it's the user's responsibility to
> set up the release of a resource. In both cases resource management is
> not encapsulated.

It's not, but let's not forget you don't pay the price of writing the
capsule.

Would I recommend ScopeGuard instead of smart pointers? No. Would I
recommend it over writing a little class of limited utility? Yes. Would
I prefer it to try/finally even if I had the latter? Often. Use judgment
and the proper tool for the job.


Andrei

kevin cline

unread,
May 6, 2005, 6:19:25 AM5/6/05
to

Roshan Naik wrote:

Roshan Naik wrote:
> I know that using the finally block (in Java or C#) to dispose
resources is
> considered inferiror to RAII.

> However I recently came accross a little C++ example that used some
> compiler's __finally language extension
> that made me rethink there might be some value in
finally...sometimes.
>
> The code was something to this effect (roughly)....
>
> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>
>
> Clearly there is no resrouce acquisistion/disposal going on here.
Just
> change some state , do some work, and then reset the state.
> And here RAII can be put to work (and ScopeGuard comes to mind), but
it is
> not at all natural to use destructors for doing such things.

It will seem perfectly natural after a bit of practice. And this sort
of thing almost never happens exactly once in an application. In your
example there are seven lines of code for controlling the cursor,
wrapped around the one line the programmer really wanted to write. How
many times are you willing to cut-and-paste those seven lines to save
writing one ten-line class? How many times are you willing to read
those seven lines on your way to finding the interesting bits that do
some time consuming work?

For me, the answer is about zero. I would create the SetWaitCursor
class immediately, because I don't want the real purpose of the code
obscured by all that noise about setting the cursor back and forth.

Andrei Alexandrescu (See Website For Email)

unread,
May 7, 2005, 7:01:31 AM5/7/05
to
Walter wrote:
> void foo()
> {
> ...
> FILE *fp = fopen( ... );
> if (fp)
> try
> {
> ....
> }
> finally
> {
> fclose(fp);
> }
> }
>
> Yes, I could wrap fp in a class with a destructor, and I would if I was
> going to use it more than once. But if it's just a one shot deal, the above
> is simpler and more direct. Ideally, the language should support both RAII
> objects and try-finally.

I think ideally, the language would support mechanisms that allow the
user to define block_cleanup code a la:

void foo()
{
...
FILE *fp = fopen( ... );

block_cleanup { fclose(fp); }
if (fp)
....
}

that is, the ability to specify code to be executed upon a scope's exit.
Refinenents would specify code to be executed upon normal or abnormal
(exceptional) leaving of the scope. (To clarify, fclose(NULL) has no
effect.)

A lot of code involving robustness in face of exceptions would be vastly
simplified using such idioms. On the other hand, it would be a pity to
burden the language proper with such syntax and semantics, so the ideal
language would embed enough growth mechanisms so as to allow things in
the block_cleanup family to be implemented as libraries.


Andrei

Roshan Naik

unread,
May 8, 2005, 1:42:29 PM5/8/05
to
> it is obvious. But, consider when there is lots of code between try and
> finally. If you keep related operations next to eachother, there is less
> chance that you will make a mistake later on down the road when modifying
> the code.

I do agree with this. Scope guard does have a downside of looking ugly and
finally block
has the problem that you mention above.

Another problem with finally is that if a exception is active when finally
block was invoked and then some operation
inside finally also throws an exception then language must decide to discard
one of the
two exceptions. Java discards the former. So thats a dirty little corner for
language designers.
I hope someday we will find a better alternative to both.


- Roshan

Seungbeom Kim

unread,
May 8, 2005, 1:35:25 PM5/8/05
to
Roland Pibinger wrote:
> On 4 May 2005 20:16:32 -0400, "Andrei Alexandrescu (See Website For
> Email)" <SeeWebsit...@moderncppdesign.com> wrote:
>
>>The problem with the code above is that the two logically paired actions
>>are spread across the code. It's the exact kind of example that
>>ScopeGuard puts to shame, because with ScopeGuard (and ON_BLOCK_EXIT)
>>you can put a current and future action together, as a single unit.
>
> Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost) equivalent to
> try/finally. The 'finally clause' is merely written before the
> statements, not below. I case of ScopeGuard the user must even call a
> second logically paired action (confusingly called 'dismiss'). In both
> cases (try/finally and ScopeGuard) it's the user's responsibility to
> set up the release of a resource. In both cases resource management is
> not encapsulated.

You call Dismiss() not to set up the release of a resource, but to
dictate that the release should be skipped, don't you? You set up some
action just in case something else fails and the control goes out of
scope, and when you see it succeeded you explicitly skip the action. I
don't agree to say that the resource management is not encapsulated in
this case; you cannot forget to release the resource.

--
Seungbeom Kim

Roshan Naik

unread,
May 8, 2005, 1:40:49 PM5/8/05
to
>> Using a finally block is helpful when:
>
>> 1) the cleanup code needs to access local variables in the function
>
> That is (at least in my mind) one of the major motivations for
> "lambda classes" (or whatever you want to call them). While
> there's been a great deal of discussion concerning the possible
> syntax and the various uses, I think that all of the suggestions
> have in common an ability to locally define a class or a
> function in which you can access local variables.

Beg to differ... but thats not a motivation for lambdas.
Using lambda instead of a finally block is like having a solution in hand
and
looking for a problem.


>
> Given such a class, it's pretty trivial to define something
> like:
>
> cleanup { some code .. } ;
>
> as a contraction for an instance of a lambda class with a
> destructor consisting of the code in the {...}.

Any reason to beleive that is more suitable than a finally block for this
task?
And lambdas are more _likely_ (i dont know the proposed semantics as of now
if there is any)
going to be more verbose than that. If its a lambda function (in future C++)
you would have to define paremater and return types...

void (void ) { some code; } // anonymous lambda function...

and if its a lambda class you would most likely need more

struct { void operator() (void) { some code;} } // anonymous lambda class

In either case you would also need to have a name if its not anonymous.

readability goes out the window... just put another try/catch inside the
"some code"
and see how readable it looks as compared to a finally block.

- Roshan

david...@ed.tadpole.com

unread,
May 8, 2005, 1:46:47 PM5/8/05
to

Joshua Lehrer wrote:
<snip>
<snip>

Ok, I doubt one of us is going to convince the other that one form is
more readable than the other. :)

I would say that your critique of try/finally is flawed. What you're
suggesting is that someone could alter the contents of a try block (I
assume putting the Do() op before the try block in your example was a
typo) and not pay attention to the rammifications of this change on the
finally block (or indeed catch blocks) that follow. Such action
strikes me as so negligent on behalf of the programmer that it's not a
compelling example of a problem with try/finally.

Cheers,

Dave

Hillel Y. Sims

unread,
May 8, 2005, 1:46:26 PM5/8/05
to

"Andrei Alexandrescu" <SeeWebsit...@moderncppdesign.com>
wrote in message news:IG12v...@beaver.cs.washington.edu...


> Hillel Y. Sims wrote:
> > using namespace boost;
> >
> > mouse.setCursor(HOUR_GLASS);
> > finally(bind(&MouseType::setCursor, ref(mouse),
NORMAL_POINTER))
> > {
> > doSomeTimeConsumingWork();
> > }
> >
> > This provides exactly the same semantics as ON_BLOCK_EXIT,
but I
> > like the stylistic look and feel better (esp. consistent use
of
> > bind() to avoid the need for ON_BLOCK_EXIT vs.
> > ON_BLOCK_EXIT_OBJ).
>
> That looks great, but why do you need ref(mouse) as opposed to
mouse? I
> think the default should be reference, and only if you need a
copy you'd
> say value(mouse). Or does that come with the generality of the
construct?
>
>


That is part of the bind() semantics -- it takes all arguments by
copy (due to issues with C++ and "forwarding constructors"); use
ref/cref wrappers to forward references. (Alternatively, a
pointer to the object (eg, "&mouse") may be passed, with the same
results.)

--
Hillel Y. Sims
hsims AT factset.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Roshan Naik

unread,
May 8, 2005, 1:49:58 PM5/8/05
to
>> Using a finally block is helpful when:
>
>> 1) the cleanup code needs to access local variables in the function
>
> That is (at least in my mind) one of the major motivations for
> "lambda classes" (or whatever you want to call them). While
> there's been a great deal of discussion concerning the possible
> syntax and the various uses, I think that all of the suggestions
> have in common an ability to locally define a class or a
> function in which you can access local variables.

Beg to differ... but thats not a motivation for lambdas.


Using lambda instead of a finally block is like having a solution in hand
and
looking for a problem.


>


> Given such a class, it's pretty trivial to define something
> like:
>
> cleanup { some code .. } ;
>
> as a contraction for an instance of a lambda class with a
> destructor consisting of the code in the {...}.

Any reason to beleive that is more suitable than a finally block for this


task?
And lambdas are more _likely_ (i dont know the proposed semantics as of now
if there is any)
going to be more verbose than that. If its a lambda function (in future C++)
you would have to define paremater and return types...

void (void ) { some code; } // anonymous lambda function...

and if its a lambda class you would most likely need more

struct { void operator() (void) { some code;} } // anonymous lambda class

In either case you would also need to have a name if its not anonymous.

readability goes out the window... just put another try/catch inside the
"some code"
and see how readable it looks as compared to a finally block.

- Roshan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Joshua Lehrer

unread,
May 8, 2005, 1:47:08 PM5/8/05
to

"Andrei Alexandrescu" <SeeWebsit...@moderncppdesign.com> wrote in
message news:IG12v...@beaver.cs.washington.edu...
> That looks great, but why do you need ref(mouse) as opposed to mouse? I
> think the default should be reference, and only if you need a copy you'd
> say value(mouse). Or does that come with the generality of the construct?

Because all other parameters are passed by copy, and boost::bind passes the
object by copy. It is too hard to remember that yor ScopeGuard behaves in a
different way. See my post under this thread.

-josh

Andrei Alexandrescu (See Website For Email)

unread,
May 9, 2005, 2:20:17 AM5/9/05
to
david...@ed.tadpole.com wrote:
> Joshua Lehrer wrote:
[snip]

>> If you keep related operations next to eachother, there is
>
> less
>
>>chance that you will make a mistake later on down the road when
>
> modifying
>
>>the code.
>>
>>Also, someone who looks at your code won't need to ask if you are
>
> cleaning
>
>>up your resource, as the resource is acquired and disposition is
>
> set-up on
>
>>the very next line. With try/finally one needs to scroll way down
>
> (given a
>
>>large function) to see if you are releasing the resource properly, or
>
> at
>
>>all.
>
> <snip>
>
> Ok, I doubt one of us is going to convince the other that one form is
> more readable than the other. :)
>
> I would say that your critique of try/finally is flawed. What you're
> suggesting is that someone could alter the contents of a try block (I
> assume putting the Do() op before the try block in your example was a
> typo) and not pay attention to the rammifications of this change on the
> finally block (or indeed catch blocks) that follow. Such action
> strikes me as so negligent on behalf of the programmer that it's not a
> compelling example of a problem with try/finally.

Agreed, but then the same can be said about manual resource management
and many other bugs: forgetting to free() a block, fclose() a file etc.
on some execution path is negligent on behalf of the programmer and not
a problem with free() or fclose(). Indeed, it's not a problem with
those, but instead there is a problem with the underlying idiom.

I, for one, am convinced that cleanup { ... } block inserted next to the
corresponding "create mess" code is a superior idiom to which
try/finally doesn't hold a candle. In fact I am so convinced, I'm not
even deterred by the fact that it's not present in today's popular
languages. :o) Maybe in 15 years it will be common, and people will look
at weaker idioms attempting to do the same thing with the contempt they
look now at the all-declarations-at-the-top-of-each-function idiom.

In fact, at the risk of breaking my NDA, here's a fragment from the WUJ
magazine, year 2020: "Old die-hard vets still use the awkward
try/finally idiom to take care of simple function-level cleanup. This
relic of Java still shows itself up in old code that you might need to
maintain. It's officially deprecated, but now in the days of pluggable
compilers and modularly extensible languages, you can use pretty much
any language construct you want. (Besides, who cares about the standards
when Cortexsoft supports something.) In short, finally does pretty much
what cleanup { ... } does, except that it puts everything exactly in the
wrong place and adds baroque syntax on top, to the end of thoroughly
messing up the logic of the function it contaminates."


Andrei

Joshua Lehrer

unread,
May 9, 2005, 6:13:15 AM5/9/05
to

<david...@ed.tadpole.com> wrote in message
news:1115373848....@f14g2000cwb.googlegroups.com...

>
> Joshua Lehrer wrote:
> <snip>
> >
> > As you point out, in a lengthy function, try/finally puts the "undo"
> > operation is far away from your "do" operation. If you change your
> > operation at the top, you may forget that you need to scroll all the
> way
> > down to the finally block to fix the undo operation. Sure, in a
> SIMPLE
> > example such as:
> >
> > do();
> > try {
> > } finally {
> > undo();
> > }
> >
> I would say that your critique of try/finally is flawed. What you're
> suggesting is that someone could alter the contents of a try block (I
> assume putting the Do() op before the try block in your example was a
> typo) and not pay attention to the rammifications of this change on the

No. It is not a typo. You can not configure the undo() to 'finally' run,
unless you are sure that it ran successfully. The only way to do this is
start the try block AFTER you are 100% sure that do() completed succesfully
and did not throw. If "do()" were to throw, you do not want "undo()" to
run because "do()" never completed.

This is yet another example of objects being superior to try/finally. The
language guarantees that object's destructors won't get run unless the
object was constructed successfully. If you had an object:

struct doer {
doer() { do(); }
~doer() { undo(); }
};

Then you are sure that undo() will only be called if do() did not throw. If
you wrote the code with try/finally blocks, it is possible for someone to
write it incorrectly, in the way that you point out:

try {
do();
} finally {
undo();
}

In this code, if "do();" throws, "undo();" will, incorrectly, be called.


> finally block (or indeed catch blocks) that follow. Such action
> strikes me as so negligent on behalf of the programmer that it's not a
> compelling example of a problem with try/finally.
>

********
"Write code not so that it can be maintained correctly, but so that it is
harder to maintain it incorrectly."
********

By using a try/finally, you are making it too easy for a programmer to be
negligent. By using ScopeGuard, or a stack based object, you encourage
proper maintenance.

Am I negligent if I make a mistake modifying your code, when you write
spaghetti code like this:

do(1);
try {
do(2);
try {
do(3);
try {
foo();
} finally {
undo(3);
}
} finally {
undo(2);
}
} finally {
undo(1);
}

BTW, is the above code correct? Is there a nesting bug? Isn't it easier to
review the code if you see this instead:

{
do(1);
ON_BLOCK_EXIT(undo,1);

do(2);
ON_BLOCK_EXIT(undo,2);

do(3);
ON_BLOCK_EXIT(undo,3);

foo();
}


joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Roland Pibinger

unread,
May 9, 2005, 6:34:10 AM5/9/05
to
On 8 May 2005 13:35:25 -0400, Seungbeom Kim <musi...@bawi.org> wrote:

>Roland Pibinger wrote:
>> Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost) equivalent to
>> try/finally. The 'finally clause' is merely written before the
>> statements, not below. I case of ScopeGuard the user must even call a
>> second logically paired action (confusingly called 'dismiss'). In both
>> cases (try/finally and ScopeGuard) it's the user's responsibility to
>> set up the release of a resource. In both cases resource management is
>> not encapsulated.
>
>You call Dismiss() not to set up the release of a resource, but to
>dictate that the release should be skipped, don't you?

But 'commit()' would be a more intuitive name.

>You set up some
>action just in case something else fails and the control goes out of
>scope, and when you see it succeeded you explicitly skip the action. I
>don't agree to say that the resource management is not encapsulated in
>this case; you cannot forget to release the resource.

You (the user) must set up some action. Therefore resource management
is not encapsulated. I have yet to see a convincing example where you
have so many different resource types in a program that you cannot
afford to encapsulate each.

Best wishes,
Roland Pibinger

Dave Harris

unread,
May 9, 2005, 8:15:43 AM5/9/05
to
wal...@digitalmars.nospamm.com (Walter) wrote (abridged):

> void foo()
> {
> ...
> FILE *fp = fopen( ... );
> if (fp)
> try
> {
> ....
> }
> finally
> {
> fclose(fp);
> }
> }

I believe that particular case is already handled by:

if (boost::shared_ptr<FILE> fp( fopen( ... ), fclose )) {
// ...
}


> Using a finally block is helpful when:
>
> 1) the cleanup code needs to access local variables in the function
>
> 2) it's a one use issue; i.e. when making a class just for one use would
> wind up cluttering the code

In the example you gave, we only need one local variable, fp, and the
cleanup is already encapsulated down to a simple function call. So
something rather generic like shared_ptr is enough.

I imagine there are more complicated cases where this won't work, but I
distrust complicated code. Maybe it would be better to simplify it.

-- Dave Harris, Nottingham, UK.

ka...@gabi-soft.fr

unread,
May 9, 2005, 6:26:26 PM5/9/05
to
Roshan Naik wrote:
> >> Using a finally block is helpful when:

> >> 1) the cleanup code needs to access local variables in the
function

> > That is (at least in my mind) one of the major motivations
> > for "lambda classes" (or whatever you want to call them).
> > While there's been a great deal of discussion concerning the
> > possible syntax and the various uses, I think that all of
> > the suggestions have in common an ability to locally define
> > a class or a function in which you can access local
> > variables.

> Beg to differ... but thats not a motivation for lambdas.
> Using lambda instead of a finally block is like having a
> solution in hand and looking for a problem.

I don't see why. What you want is code that executes when the
scope ends. Creating an unnamed object (with local scope, not
temporary) whose destructor contains the code is the obvious
solution; it is, in fact, the standard C++ solution. A lambda
object just makes accessing local variables easier.

> > Given such a class, it's pretty trivial to define something
> > like:

> > cleanup { some code .. } ;

> > as a contraction for an instance of a lambda class with a
> > destructor consisting of the code in the {...}.

> Any reason to beleive that is more suitable than a finally
> block for this task?

Yes. The cleanup code is where it should be, not somewhere down
at the bottom of the block where a maintenance programmer
doesn't see it, and doesn't update it when necessary.

> And lambdas are more _likely_ (i dont know the proposed
> semantics as of now if there is any) going to be more verbose
> than that. If its a lambda function (in future C++) you would
> have to define paremater and return types...

> void (void ) { some code; } // anonymous lambda function...

> and if its a lambda class you would most likely need more

> struct { void operator() (void) { some code;} } // anonymous lambda
class

> In either case you would also need to have a name if its not
> anonymous.

There was quite a long thread about lambdas here not too long
ago. One thing was clear -- whatever the formal semantics
adopted (class or function), there was a demand that the
"frequent" uses be simple, and not too verbose. There's still
no formal proposal that I'm aware of, but I think that there is
a strong consensus that you shouldn't have to write a full class
declaration (or function definition) when all you want is a
single function and the compiler is capable of deducing the
required types.

> readability goes out the window... just put another try/catch
> inside the "some code" and see how readable it looks as
> compared to a finally block.

Just as readable as putting a try/catch block inside a finally
block, no?

--
James Kanze GABI Software


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

ka...@gabi-soft.fr

unread,
May 9, 2005, 6:26:05 PM5/9/05
to
Hillel Y. Sims wrote:
> "James Kanze" <ka...@none.news.free.fr> wrote in message
> news:4279ef04$0$315$626a...@news.free.fr...

> > FILE *fp = fopen( ... ) ;
> > if ( fp != NULL ) {
> > cleanup { fclose( fp ) ; }
> > }

> What do you think about the following?

> FILE* fp = fopen("xyz","r");
> if (fp != 0) {
> finally(bind<int>(fclose, fp)) {
> process_file(fp);
> }
> }

> I've just copy/pasted that from a source file that compiled
> and linked successfully.

Really? Using which compiler and which libraries? (I find it
very misleading, for example, that bind<int> can be used with a
FILE*. Supposing an appropriate finally, bind<FILE*> might not
be too bad, but I still prefer the syntax of cleanup -- a simple
inline function.)

> > Except that it's still a bad example, since in the normal
> > case, I'd certainly want to handle errors in the fclose, and
> > would thus naturally write something along the lines of:

> > if ( fp != NULL ) {
> > try {
> > ...
> > if ( fclose( fp ) != 0 ) {
> > // handle errors...
> > }
> > } catch ( ... ) {
> > fclose( fp ) ; // can't do much about errors
> here,
> > // but it doesn't matter, the
> > // operation is hosed anyway.
> > throw ;
> > }
> > }

> > (Except, of course, I'd actually be using fstream, so the
> > try/catch would be unnecessary. Unless I was outputting and
> > wanted to delete the corrupted file I'd just generated.)

> What if the filename itself has also been corrupted when you
> make that call to remove(filename)?

And why would the filename be corrupted? Anymore than anything
else, of course -- if lower level code writes through an
uninitialized pointer, there's not much you can do to protect
yourself.

> Besides, isn't fclose() a no-throw operation?

One would hope so, given that it is a C function:-). And of
course, if it wasn't, I'd be more careful about using it in a
catch block.

--
James Kanze GABI Software

Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

David Turner

unread,
May 9, 2005, 6:53:11 PM5/9/05
to
I've been following this thread for a few days, and here is my take on
the situation:

First: many things that are not obviously resources, are.
Cursor-changes included. However, it would be nice to have a
better-understood term for the set of entities bound by
initialization/cleanup contracts or pre- and postconditions. Inanouts?
;-)

Second: Finally / block cleanup / (insert variation here) is dangerous
for two essential but related reasons:

1. We're back to that age-old problem of forgetting that cleanup is
required.
2. (Perhaps controversial?) Cleanup for an entity is implied by its
initialization; a transaction making use of an entity has no business
explicitly dictating its finalization. By way of analogy, we don't
write "now switch off the stove" when writing recipes. As
initialization and cleanup are logically associated, it seems sensible
that they should be spacially associated as well, whereas code making
heavy use of "finally" tends to be afflicted with a cluttering of
concerns.

Just in case (2) isn't clear, what I'm saying is that it makes no sense
for a function making use of an object (of whatever sort) to contain
code relating to its initialization and finalization, contractual
inanout obligations, etc. These topics are presumably not the main
focus of the function. The point of a high-level language is to
abstract; to move away from the nit-picking detail required in
instructing the machine. RAII provides a rather good mechanism for
doing so; "finally" is, IMHO, a step backwards.

Regards
David Turner

ka...@gabi-soft.fr

unread,
May 10, 2005, 7:58:05 AM5/10/05
to

FWIW: I think I prefer your slightly longer name than my
"cleanup".

> Refinenents would specify code to be executed upon normal or
> abnormal (exceptional) leaving of the scope. (To clarify,
> fclose(NULL) has no effect.)

That's an interesting idea. More generally, it might be
interesting to be able to distinguish in a destructor whether it
was called normally, or because of stack unwinding. I've been
using a special function for this (commit), and most of the
time, it's not a bother, but I can think of cases where it might
be.

> A lot of code involving robustness in face of exceptions would
> be vastly simplified using such idioms. On the other hand, it
> would be a pity to burden the language proper with such syntax
> and semantics, so the ideal language would embed enough growth
> mechanisms so as to allow things in the block_cleanup family
> to be implemented as libraries.

Would be nice.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

ka...@gabi-soft.fr

unread,
May 10, 2005, 7:59:35 AM5/10/05
to
Roland Pibinger wrote:
> On 8 May 2005 13:35:25 -0400, Seungbeom Kim <musi...@bawi.org>
wrote:
> >Roland Pibinger wrote:
> >> Oops! ScopeGuard/ON_BLOCK_EXIT is logically (almost)
> >> equivalent to try/finally. The 'finally clause' is merely
> >> written before the statements, not below. I case of
> >> ScopeGuard the user must even call a second logically
> >> paired action (confusingly called 'dismiss'). In both cases
> >> (try/finally and ScopeGuard) it's the user's responsibility
> >> to set up the release of a resource. In both cases resource
> >> management is not encapsulated.

> >You call Dismiss() not to set up the release of a resource,
> >but to dictate that the release should be skipped, don't you?

> But 'commit()' would be a more intuitive name.

That would depend on the context, I think. But I'm not sure
"intuitive" would be the word I would choose: more usual, or
more expected, perhaps.

In the end, it is a question of view point. In Andrei's
ScopeGuard, you define finalization actions, then say dismiss to
say you don't need them. In a traditional transaction, you
carry out a number of actions, then call commit to say you want
to make them permanent.

> >You set up some action just in case something else fails and
> >the control goes out of scope, and when you see it succeeded
> >you explicitly skip the action. I don't agree to say that the
> >resource management is not encapsulated in this case; you
> >cannot forget to release the resource.

> You (the user) must set up some action. Therefore resource
> management is not encapsulated. I have yet to see a
> convincing example where you have so many different resource
> types in a program that you cannot afford to encapsulate each.

It's not a question of not being able to afford to encapsulate
each. It's more a question of handling a couple of one-of cases
easily. If you find yourself handling the same resource several
times with a ScopeGuard, then I do think you're abusing it -- if
you're doing the same thing several times, there must be an
underlying concept which needs abstracting.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Andrei Alexandrescu (See Website for Email)

unread,
May 10, 2005, 8:03:49 AM5/10/05
to
Roland Pibinger wrote:
> You (the user) must set up some action. Therefore resource management
> is not encapsulated. I have yet to see a convincing example where you
> have so many different resource types in a program that you cannot
> afford to encapsulate each.

It's hard to show you an example because obviously that would be too
large. :o) Suffice to say that Petru and I are getting praising emails
for ScopeGuard more than for any other article I've written (truth be
told, that might just as well mean that the others are terrible), and
that people I've worked long ago have consistently brought ScopeGuard
as one of their first tools whenever they moved to new companies.

Andrei

Nicola Musatti

unread,
May 10, 2005, 9:02:43 AM5/10/05
to

Roshan Naik ha scritto:

> I know that using the finally block (in Java or C#) to dispose
resources is
> considered inferiror to RAII.
> However I recently came accross a little C++ example that used some
> compiler's __finally language extension
> that made me rethink there might be some value in
finally...sometimes.
>
> The code was something to this effect (roughly)....
>
> mouse.setCursor(HOUR_GLASS); // change state
> try {
> doSomeTimeConsumingWork( );
> }
> __finally { // non standard extension
> mouse.setCursor(NORMAL_POINTER); //reset state
> }
>
>
> Clearly there is no resrouce acquisistion/disposal going on here.
Just
> change some state , do some work, and then reset the state.
> And here RAII can be put to work (and ScopeGuard comes to mind), but
it is
> not at all natural to use destructors for doing such things. That
> immediately feels more like a hack.... and hides the intent of the
code
> somewhere behind the scenes.
>
> Also it seems useful in cases where you want to guarantee the
restoration of
> an invariant.

This specific problem - setting/resetting the cursor - is a wonderful
example of how using a class is a far superior approach. If the cursor
was a local setting of your code snippet this would really boil down to
personal taste. However the cursor is a portion of the application's
global state that needs to be modified throughout the GUI subsystem.
This means that if within your doSomeTimeConsumingWork() someone else
applies your idiom the cursor would be reset too early. On the other
hand it is very easy to provide your class with a static counter which
is increased in the constructor and decreased in the destructor; the
cursor is then changed only when the counter changes from 0 to 1 and
viceversa.

>From this point it wouldn't be to difficult to modify again to keep a
static stack of cursor shapes so as to be able to handle more than to
of them.

Not only this is a problem that deserves a custom class, but it's also
one class that should be in every GUI framework.

Cheers,
Nicola Musatti

Nicola Musatti

unread,
May 10, 2005, 9:02:14 AM5/10/05
to

kevin cline ha scritto:
> Roshan Naik wrote:
[...]

> > Clearly there is no resrouce acquisistion/disposal going on here.
> Just
> > change some state , do some work, and then reset the state.
> > And here RAII can be put to work (and ScopeGuard comes to mind),
but
> it is
> > not at all natural to use destructors for doing such things.
>
> It will seem perfectly natural after a bit of practice. And this
sort
> of thing almost never happens exactly once in an application. In
your
> example there are seven lines of code for controlling the cursor,
> wrapped around the one line the programmer really wanted to write.
How
> many times are you willing to cut-and-paste those seven lines to save
> writing one ten-line class? How many times are you willing to read
> those seven lines on your way to finding the interesting bits that do
> some time consuming work?

Not only that, but as I pointed out in another message, in this case
the Copy&Paste solution doesn't work.

> For me, the answer is about zero. I would create the SetWaitCursor
> class immediately, because I don't want the real purpose of the code
> obscured by all that noise about setting the cursor back and forth.

This is an important point: the perfect candidate for RAII is an
activity that is conceptually at a lower level than the current
function.

Cheers,
Nicola Musatti

Peter Dimov

unread,
May 10, 2005, 9:00:24 AM5/10/05
to
Joshua Lehrer wrote:
> Using scopeguard's native object creation factories are superior to
> mixing scopeguard and boost::bind because boost::bind requires
> dynamic memory allocation and a virtual function call, scopeguard
> does not.

This is not strictly correct. boost::function requires dynamic memory
allocation and an indirect call. boost::bind itself does none of these. You
can use the ScopeGuard const& technique to implement

ON_BLOCK_EXIT( arbitrary-function-object );

which then allows you to use boost::bind to create the arbitrary function
object. Then you can create an alias

ON_BLOCK_EXIT_(( boost-bind-args ));

if you like. :-)

Roland Pibinger

unread,
May 10, 2005, 9:03:23 AM5/10/05
to
On 6 May 2005 04:05:26 -0400, Andrei Alexandrescu
<SeeWebsit...@moderncppdesign.com> wrote:

>Roland Pibinger wrote:
>> I case of ScopeGuard the user must even call a
>> second logically paired action (confusingly called 'dismiss').
>
>Nonono. "Suggestively" called dismiss. :o)

Recently I saw a ScopeGuard implementation that hat a commit() instead
of the dismiss(). IMO, a more intuitive name.

>> In both
>> cases (try/finally and ScopeGuard) it's the user's responsibility to
>> set up the release of a resource. In both cases resource management is
>> not encapsulated.
>
>It's not, but let's not forget you don't pay the price of writing the
>capsule.
>Would I recommend ScopeGuard instead of smart pointers? No. Would I
>recommend it over writing a little class of limited utility? Yes.

But how many different resources must be managed in a typical program
so that you cannot afford to encapsulate them? Any examples? IMO,
resource acquisition/release should always be encapsulated.

Best regards,
Roland Pibinger

Walter

unread,
May 10, 2005, 10:30:29 AM5/10/05
to

"Andrei Alexandrescu (See Website For Email)"
<SeeWebsit...@moderncppdesign.com> wrote in message
news:IG2v8...@beaver.cs.washington.edu...

> I think ideally, the language would support mechanisms that allow the
> user to define block_cleanup code a la:
>
> void foo()
> {
> ...
> FILE *fp = fopen( ... );
> block_cleanup { fclose(fp); }
> if (fp)
> ....
> }
>
> that is, the ability to specify code to be executed upon a scope's exit.

But isn't that what the finally block of try-finally does?

> Refinenents would specify code to be executed upon normal or abnormal
> (exceptional) leaving of the scope.

Having a catch can handle the exceptional leavings.

Hillel Y. Sims

unread,
May 10, 2005, 10:24:02 AM5/10/05
to

"Andrei Alexandrescu (See Website For Email)"
<SeeWebsit...@moderncppdesign.com> wrote in message
news:IG2v8...@beaver.cs.washington.edu...
>
> I think ideally, the language would support mechanisms that
allow the
> user to define block_cleanup code a la:
>
> void foo()
> {
> ...
> FILE *fp = fopen( ... );
> block_cleanup { fclose(fp); }
> if (fp)
> ....
> }
>
> that is, the ability to specify code to be executed upon a
scope's exit.

It does, and I've created some (with some help from other
libraries). I call my variation "finally":

finally.cxx (complete listing)
----------------
#include <stdio.h>
#include "scopeguard.h"
#include <boost/bind.h>
#include "finally.h" // "finally", "GuardRegion"

using namespace boost;

void process_file(FILE*) {}

int main()
{
FILE* const fp = fopen("xyz","r");


if (fp != 0) {
finally(bind<int>(fclose, fp)) {
process_file(fp);
}
}
}

---------------

<termdump>
$ build finally.cxx
- compiling FINALLY.CXX...
Compaq C++ V6.5-041 for OpenVMS Alpha V7.3-2


- linking FINALLY.EXE...
Compaq C++ CXXLINK V6.5-041


************
**
** successfully built FINALLY.EXE **
**
************
</termdump>

> Refinenents would specify code to be executed upon normal or
abnormal
> (exceptional) leaving of the scope.

I call this form "GuardRegion":

----
void DataHandler_t::fetch()
{
GuardRegion(bufguard, bind(&Buf_t::clear, ref(m_buf))) {
fetch_impl(m_buf); // dispatch to subclass (may throw)
bufguard.Dismiss();
}
}
----

>
> A lot of code involving robustness in face of exceptions would
be vastly
> simplified using such idioms.

I've been using "finally" and "GuardRegion" in production code
for about a year now, and from my experience, I completely agree!
I find them especially powerful and clean for multi-threaded
programming, with respect to dealing with pthread cancellation
exceptions (assuming an OS where it actually throws a C++
exception). Talk about rock-solid high-performance applications!

(Another nice one for multi-threading is "LockRegion", created by
Joshua Lehrer:

void App::func(const string& key)
{
shared_ptr<Obj> pobj;
LockRegion(mapMutex) {
map<string, shared_ptr<Obj> >::const_iterator p
= sharedMap.find(key);
if (p != sharedMap.end()) pobj = p->second;
}
pobj->func();
})

> so as to allow things in
> the block_cleanup family to be implemented as libraries.
>

In fact, "finally" and "GuardRegion" are completely
standard-compliant and portable, and easily built (<10 lines of
code) on top of the scopeguard library (requiring only two minor
modifications to scopeguard.. ScopeGuard::Dismiss() needs to
return the old bool value, and ScopeGuard::Execute() needs to
temporarily disable pthread-cancellation while executing the
cleanup function).

--
Hillel Y. Sims
hsims AT factset.com

FactSet Research Systems


ps:


> (To clarify, fclose(NULL) has no effect.)

I don't believe that..
http://www.opengroup.org/onlinepubs/009695399/functions/fclose.html
<quote>The fclose() function shall cause the stream pointed to by
stream to be flushed and the associated file to be
closed</quote> -- and nothing about null pointers in there..

fclose(0) returns -1 and sets EBADF status code on my system.. it
seems like undefined behavior.

david...@ed.tadpole.com

unread,
May 10, 2005, 3:39:33 PM5/10/05
to

Joshua Lehrer wrote:
> <david...@ed.tadpole.com> wrote in message
<snip>

>>>
>> I would say that your critique of try/finally is flawed. What
you're
>> suggesting is that someone could alter the contents of a try block
(I
>> assume putting the Do() op before the try block in your example was
a
>> typo) and not pay attention to the rammifications of this change on
the
>
> No. It is not a typo. You can not configure the undo() to 'finally'
run,
> unless you are sure that it ran successfully. The only way to do
this is
> start the try block AFTER you are 100% sure that do() completed
succesfully
> and did not throw. If "do()" were to throw, you do not want "undo()"
to
> run because "do()" never completed.
>
<snip>

You're absolutely right - I realised I was talking nonsense only after
I'd pressed send! I did e-mail the moderator to ask my post not to be
admitted but I guess I was a little late.

The arguments that you and Andrei have put forward certainly persuade
me that the scope guard approach has advantages over the try/finally
approach. I'll now weasle out of my original position and say that I
now find both approaches sub-optimal. If the scope guard technique was
enshrined in the standard and had some syntax to obviate the need for
ugly preprocessor macros then I'd be far more favourable towards it.

Grouping logically related operations is positive but I also like the
explicit nature of try/finally that allows the question of "what
clean-up *must* happen at the end of this function?" to be answered
with a quick scan of the code and not a check for scope-guarded objects
followed by a check on the side-effects of the relevant destructors.

Cheers,

Dave

The Sim

unread,
May 10, 2005, 5:32:19 PM5/10/05
to
<ka...@gabi-soft.fr> wrote in message
news:1115644850.0...@f14g2000cwb.googlegroups.com...

> Hillel Y. Sims wrote:
>
> > FILE* fp = fopen("xyz","r");
> > if (fp != 0) {
> > finally(bind<int>(fclose, fp)) {
> > process_file(fp);
> > }
> > }
>
> > I've just copy/pasted that from a source file that compiled
> > and linked successfully.
>
> Really? Using which compiler and which libraries?

Compaq/HP C++ V6.5 on OpenVMS (an EDG-based compiler).
boost/bind.h, a slightly modified scopeguard.h (from A.
Alexandrescu / P. Marginean), and my local library which defines
"finally".

> (I find it
> very misleading, for example, that bind<int> can be used with a
> FILE*.

fclose() is declared extern "C" and returns int. The first
template argument to bind() specifies the return type of the
function object; bind() has issues deducing the return type
automatically for extern "C" functions. bind<int> is correct in
this case.

> Supposing an appropriate finally, bind<FILE*> might not
> be too bad, but I still prefer the syntax of cleanup -- a
simple
> inline function.)
>

>


> > What if the filename itself has also been corrupted when you
> > make that call to remove(filename)?
>
> And why would the filename be corrupted? Anymore than anything
> else, of course -- if lower level code writes through an
> uninitialized pointer, there's not much you can do to protect
> yourself.

I'm a strong advocate against the use of catch(...) in almost any
form, due to the fact that assuming that it does not interfere
badly with OS-based exceptions is (at the least) not portable.
There is particularly no need for catch(...) { throw; } when
RAII-based alternatives serve the same purpose without the
platform-dependent issues.

>
> > Besides, isn't fclose() a no-throw operation?
>
> One would hope so, given that it is a C function:-). And of
> course, if it wasn't, I'd be more careful about using it in a
> catch block.
>

Sorry, I misread that part of your message.

--
Hillel Y. Sims
hsims AT factset.com
FactSet Research Systems

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Joshua Lehrer

unread,
May 10, 2005, 5:36:58 PM5/10/05
to

<ka...@gabi-soft.fr> wrote in message
news:1115644850.0...@f14g2000cwb.googlegroups.com...
> Hillel Y. Sims wrote:
> > "James Kanze" <ka...@none.news.free.fr> wrote in message
> > news:4279ef04$0$315$626a...@news.free.fr...
>
> > > FILE *fp = fopen( ... ) ;
> > > if ( fp != NULL ) {
> > > cleanup { fclose( fp ) ; }
> > > }
>
> > What do you think about the following?
>
> > FILE* fp = fopen("xyz","r");
> > if (fp != 0) {
> > finally(bind<int>(fclose, fp)) {
> > process_file(fp);
> > }
> > }
>
> > I've just copy/pasted that from a source file that compiled
> > and linked successfully.
>
> Really? Using which compiler and which libraries?

Compaq C++ V6.5 on OpenVMS with Rougewave, and an old boost port. Finally
is an internal custom macro.

> (I find it
> very misleading, for example, that bind<int> can be used with a
> FILE*. Supposing an appropriate finally, bind<FILE*> might not
> be too bad, but I still prefer the syntax of cleanup -- a simple
> inline function.)

The first template parameter to bind<> is the return type. As "fclose" is
'extern "C"', on our platform, bind can not determine the return type
automatically, so we have to supply it for bind, hence, bind<int>.

joshua lehrer
factset research systems
NYSE:FDS

The Sim

unread,
May 10, 2005, 5:33:30 PM5/10/05
to
"David Turner" <dktu...@gmail.com> wrote in message
news:1115642683.7...@o13g2000cwo.googlegroups.com...

> RAII provides a rather good mechanism for
> doing so; "finally" is, IMHO, a step backwards.


I agree with you. But what if we specify "finally" itself in
terms of RAII and generic function objects:

void fetch(OBJ*); // (eg: from some poorly-written third-party
API)
void post_fetch(OBJ*);

void myfunc(OBJ* obj)
{
finally(bind(&post_fetch, obj)) {
fetch(obj);
}
}

(the above code example is completely standard C++ and compiles
successfully on my platform)

hys


--
Hillel Y. Sims
hsims AT factset.com
FactSet Research Systems

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Jeff Flinn

unread,
May 10, 2005, 10:34:16 AM5/10/05
to

"Andrei Alexandrescu" <SeeWebsit...@moderncppdesign.com> wrote in
message news:IG12v...@beaver.cs.washington.edu...
> Hillel Y. Sims wrote:
>> using namespace boost;
>>
>> mouse.setCursor(HOUR_GLASS);
>> finally(bind(&MouseType::setCursor, ref(mouse), NORMAL_POINTER))
>> {

...

> That looks great, but why do you need ref(mouse) as opposed to mouse?

A feature of boost::bind is that the arguments are passed by value. Atleast
for me, the majority of the time, the function resulting from bind, is not
executed until the scope which call bind has been long since exited. I
rarely use boost::ref, and would hate to wrap all arguments in value(...)
calls.

Jeff Flinn

Roshan Naik

unread,
May 10, 2005, 7:59:11 PM5/10/05
to
> There was quite a long thread about lambdas here not too long
> ago. One thing was clear -- whatever the formal semantics
> adopted (class or function), there was a demand that the
> "frequent" uses be simple, and not too verbose.

That would be nice. Preferably even in the presence of templates! Would you
recall the topic of that thread ? Perhaps
I can use google groups to peruse it.

-Roshan

Peter Dimov

unread,
May 11, 2005, 3:53:56 AM5/11/05
to
ka...@gabi-soft.fr wrote:

> Hillel Y. Sims wrote:
>
>> What do you think about the following?
>
>> FILE* fp = fopen("xyz","r");
>> if (fp != 0) {
>> finally(bind<int>(fclose, fp)) {
>> process_file(fp);
>> }
>> }
>
>> I've just copy/pasted that from a source file that compiled
>> and linked successfully.
>
> Really? Using which compiler and which libraries? (I find it
> very misleading, for example, that bind<int> can be used with a
> FILE*.

The int is the return type. It's only required if the implementation of bind
can't deduce the return type of extern "C" functions, otherwise bind(
fclose, fp ) is enough.

(There is no way to portably extract the return type of an arbitrary extern
"C" function pointer in C++03.)

Andrei Alexandrescu (See Website For Email)

unread,
May 11, 2005, 6:34:16 AM5/11/05
to
Hillel Y. Sims wrote:
> "Andrei Alexandrescu (See Website For Email)"
>> (To clarify, fclose(NULL) has no effect.)

>I don't believe that..
>http://www.opengroup.org/onlinepubs/009695399/functions/fclose.html
><quote>The fclose() function shall cause the stream pointed to by
>stream to be flushed and the associated file to be
>closed</quote> -- and nothing about null pointers in there..

>fclose(0) returns -1 and sets EBADF status code on my system.. it
>seems like undefined behavior.

I knew I should check before posting... thanks for the correx.

Andrei

Andrei Alexandrescu (See Website For Email)

unread,
May 11, 2005, 7:01:25 AM5/11/05
to
david...@ed.tadpole.com wrote:
> You're absolutely right - I realised I was talking nonsense only after
> I'd pressed send! I did e-mail the moderator to ask my post not to be
> admitted but I guess I was a little late.
>
> The arguments that you and Andrei have put forward certainly persuade
> me that the scope guard approach has advantages over the try/finally
> approach.

Hey hey. In years of being on the Usenet I haven't seen this. I recall I
was chatting with a friend and we agreed that nobody on the Usenet can
convince anybody else of anything. :o) Congratulations!

> Grouping logically related operations is positive but I also like the
> explicit nature of try/finally that allows the question of "what
> clean-up *must* happen at the end of this function?" to be answered
> with a quick scan of the code and not a check for scope-guarded objects
> followed by a check on the side-effects of the relevant destructors.

Now here's an interesting thing. As I've said in another post (the
example with the database and the in-memory cache) guards are often
sprinkled through a function, and not concentrated in one point. This is
because certain actions of a function must be undone upon the rest of
the function failing; not all, and not lumped together.


Andrei

Andrei Alexandrescu (See Website For Email)

unread,
May 11, 2005, 7:11:12 AM5/11/05
to
Walter wrote:
> "Andrei Alexandrescu (See Website For Email)"
> <SeeWebsit...@moderncppdesign.com> wrote in message
> news:IG2v8...@beaver.cs.washington.edu...
>
>>I think ideally, the language would support mechanisms that allow the
>>user to define block_cleanup code a la:
>>
>>void foo()
>>{
>> ...
>> FILE *fp = fopen( ... );
>> block_cleanup { fclose(fp); }
>> if (fp)
>> ....
>>}
>>
>>that is, the ability to specify code to be executed upon a scope's exit.
>
>
> But isn't that what the finally block of try-finally does?

Ah, I meant, "the ability to specify, at any point inside a scope, code
to be executed upon that scope's exit".

>>Refinenents would specify code to be executed upon normal or abnormal
>>(exceptional) leaving of the scope.
>
> Having a catch can handle the exceptional leavings.

Well modulo the known problems of the catch with ellipsis. :o}

There's a thing about try/catch that this thread made me understand. The
common view is that try/catch allows you to focus on the main logic of
the function and on the error conditions in separate places etc. But you
still have a scope and a level of indentation there for the try part
(IMHO indentation adds intellectual overhead). Besides, the places in
which you actually do work in the catch block that is related to the
error itself are only a few in an application (centralized error
handling, right?) Most of the time, you just want to take contingency
measures to cover your *own*, um, traces. So what you really want in a
function that has multiple failure point is, "if things succeeeded up to
this point and something bad happens later, I'd need this action to be
executed". try's and catch's and finally's allow that, but not in a
simple and direct way.


Andrei

Andrei Alexandrescu (See Website For Email)

unread,
May 11, 2005, 7:09:39 AM5/11/05
to
David Turner wrote:
> Just in case (2) isn't clear, what I'm saying is that it makes no sense
> for a function making use of an object (of whatever sort) to contain
> code relating to its initialization and finalization, contractual
> inanout obligations, etc. These topics are presumably not the main
> focus of the function. The point of a high-level language is to
> abstract; to move away from the nit-picking detail required in
> instructing the machine. RAII provides a rather good mechanism for
> doing so; "finally" is, IMHO, a step backwards.

That's true, however there's more about it than that. Focusing on
resources only catches part of the story. It's not about resources as
much as about the basics of doing and undoing actions.

The example I give in my talk on ScopeGuard is a simple function that
adds a record to a database, and to the in-memory cache of the database.
The function has two failure points as both actions might fail. While
considering an entry in a vector a resource and writing a class
PopBacker to dispose of it works, it is a stretch. You care about
removing an entry from the vector if the database action fails, and an
implementation based on ScopeGuard is shorter and arguably easier to
understand than other approaches.

Furthermore, ScopeGuard scales up. In a function with N failure points
there is no increase in indentation and a linear blowup in size for
planting the appropriate guards. Defining a little class for each undo
of an action is a linear blowup, but of much larger proportions, and
scatters stuff all over the place (classes with awkward names such as
VectorAppender and DatabaseRowAdder and CounterIncrementer, oh joy!),
some of which might be reusable (if you care to sift through the wads of
code or documentation), and most of which isn't. Doing it in-situ with
try blocks is a linear blowup in level of indentation, which I see as bad.

That's why I'm thinking - a language feature that does what ScopeGuard
does but with access to local state would be way more useful and used
than the awkward try blocks.

I see our community slowly moving towards better idioms for handling
errors. The global "errno" - can you believe that was cool at some
point? :o) - and error flags and HRESULT and singular values returned
are but an awkward first step. Then, try/catch/finally blocks are the
second. IMHO cleanup { ... } blocks would be the third. Heck, I'm
starting to talk Hegelian dialectics around here :o).


Andrei

Andrei Alexandrescu (See Website For Email)

unread,
May 11, 2005, 7:08:11 AM5/11/05