Topic: after
Author: kanze@us-es.sel.de (James Kanze US/ESC 60/3/164 #71425)
Date: 10 Aug 1994 15:30:00 GMT Raw View
In article <329tvl$5b1@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk
(Enrico Viali) writes:
|> In article <3282dk$en6@ritz.cec.wustl.edu>, jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:
|> |> Follow the thread back farther. The original poster was complaining that
|> |> templates are a pain and didn't like the proposed template solution.
|> My *main* complain is that the code you may want to excute at the exit of
|> a function is not only and always deleting a pointer. You may want to
|> check a postcondition,
|> empty a collection,
|> reinstall an old new_handler
|> write on the terminal "Yahoo!! I am exiting this function!!!" :-)
|> ... whatever else...
|> (See my previous postings)
As I understood the cleanup proposal, this is possible.
Basically, `cleanup' simply provides an ad hoc way of defining and
instanciating (in one statement) a class with only a destructor *AND*
that has access to the current context.
`Cleanup' is not associated with any specific local variables (but the
associated code can access all variables that are in scope at that
time).
A `cleanup' which isn't reached in the control flow will not be
executed (perhaps the biggest advantage over `after').
The code associated with several cleanup's will be executed in the
reverse order that the cleanup's were encountered in the control flow.
Finally, it is illegal to jump over a `cleanup' in the same scope (?).
In sum, `cleanup' acts like the declaration of a variable with a
destructor (and maybe a constructor).
--
James Kanze email: kanze@lts.sel.alcatel.de
GABI Software, Sarl., 8 rue des Francs Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Thu, 11 Aug 1994 07:56:16 +0000 Raw View
In article <32837b$esc@ritz.cec.wustl.edu>
sg3235@shelob.sbc.com "John Andrew Fingerhut" writes:
>In article <776425599snz@wslint.demon.co.uk>,
>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>In article <3265bp$krg@ritz.cec.wustl.edu>
>> sg3235@shelob.sbc.com "John Andrew Fingerhut" writes:
>>
>>>In article <775917806snz@wslint.demon.co.uk>,
>>>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>>>Err, don't you like the idea of having the destructor called on
>>>>your object? Template instantiation is not a pain:
>>>
>>>It's not a pain if you don't want to work for an extra 20 minutes or longer
>>>during your link time. I refuse to use them until there isn't such an extra
>>>link time cost associated with them.
>>
>>Unless I'm very much mistaken, the class I posted was small and inline.
>>There will be no link time overhead.
>
>Oh Contrear, mon capitan (or however it's spelled ;-). I created a couple of
>template classes that were completely inline. The compiler still complained
>about not finding "C" files for the templates, created thousands of little
>files that needed to be linked in (most of which simply had typedefs in them or
>dummy functions that were never called as far as I could tell), and regenerated
>these files everytime the executable was linked even if *no* source code was
>changed (I removed the executable and relinked immediately after linking just
>to see if this would be true). Furthermore, I had to start linking like:
> CC $(OBJS) $(LIBDIR)/lib/libname.a
>instead of:
> CC $(OBJS) -L$(LIBDIR) -lname
>because the latter produced undefined symbols. Before telling me to get
>another compiler, the only other compiler I could get for that machine didn't
>even *have* templates and didn't even implement things like post
>inc(dec)rement.
I guess it's a [lack of] quality of implementation issue ;-)
--
Kevlin A P Henney
synonymicon is another word for thesaurus
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Thu, 11 Aug 1994 07:52:49 +0000 Raw View
In article <3279et$8pk@bull.saltfarm.bt.co.uk>
enrico@mround.bt.co.uk "Enrico Viali" writes:
>In article <776341012snz@wslint.demon.co.uk>, kevlin@wslint.demon.co.uk (Kevlin
> Henney) writes:
>|> Yes, after is particularly ugly and does not fit the language at all.
>|> Since exceptions are related to blocks and not functions (goto labels are
>|> the only kind of thing that have function scope), then any cleanup
>|> mechanism should somehow be related to this. Following the example of
>
>We are not talking about after has a substitute for exceptions but just
>observing that GOTOs would not harmonize (clean) well with exceptions,
> after/cleanup would.
>Besides if you think a bit about it you will see that C++ exceptions rely on
>stack unwinding, there is a strong procedural component in them.
No, I wasn't talking about after as a substitute for exceptions, just that
defining after at the function level rather than the block level is
meaningless - variables are defined at the block and not the function level,
as are there cleanup activities. You may also notice that blocks have a
strong procedural component in them - after all, this is procedural
programming ;-)
Clearly cleanup must relate to exceptions, otherwise there is no issue.
My point was that since exceptions use stack unwinding which is done per
block (wrt dtor calls, rather than discarding the actual stack frame), then
the cleanup should be defined per block, and preferably per exception
handling structure (if included in a language extension).
--
Kevlin A P Henney
synonymicon is another word for thesaurus
Author: jason@cygnus.com (Jason Merrill)
Date: Thu, 11 Aug 1994 22:56:47 GMT Raw View
>>>>> John Andrew Fingerhut <jaf3@ritz.cec.wustl.edu> writes:
> The following might solve the above mentioned problems:
> A cleanup block can be declared anywhere in an existing block. Whenever a
> block is exited, all cleanup blocks seen up to the point of the block exit
> will be executed.
That was the intent of the proposal.
Jason
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 13 Aug 1994 20:09:39 GMT Raw View
In article <Cu0z9A.9sw@hawnews.watson.ibm.com> "Kevin Cooney" <cooney@vnet.ibm.com> writes:
>There is a problem with template smart pointers. If
>B is inherited from A:
>
>void foo( Handle<A> );
>
>Handle<B> a = new A;
>foo( a ); // doesn't compile
The proposed smart pointer class for the Standard library
handles this!
How, you ask? Well, it uses member templates :-)
Something like ....
template<class X>
class Handle { ...
long *refcnt;
X* ptr;
Handle(X* x, long* ref) : refcnt(ref), ptr(x) { ++*refcnt; }
public:
Handle(X* x) : ptr(x) { refcnt = new long; ..... }
template<class T> operator Handle<T> {
return Handle<T>(ptr, refcnt); }
..
so there is an automatic conversion between handles of
X to handles of T for all T and X for which T* can be
converted to an X*.
>
>If your framework involves returning base
>classes to hidden derived-classes, there is no pretty solution. I'd
>love to see a robust template solution.
How does the above look?
(I think the author, Greg Colvin, posted the code here recently:
the above is just a demo of the technique).
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 9 Aug 1994 09:18:19 -0500 Raw View
In article <776425599snz@wslint.demon.co.uk>,
Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>In article <3265bp$krg@ritz.cec.wustl.edu>
> sg3235@shelob.sbc.com "John Andrew Fingerhut" writes:
>
>>In article <775917806snz@wslint.demon.co.uk>,
>>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>>Err, don't you like the idea of having the destructor called on
>>>your object? Template instantiation is not a pain:
>>
>>It's not a pain if you don't want to work for an extra 20 minutes or longer
>>during your link time. I refuse to use them until there isn't such an extra
>>link time cost associated with them.
>
>Unless I'm very much mistaken, the class I posted was small and inline.
>There will be no link time overhead.
Oh Contrear, mon capitan (or however it's spelled ;-). I created a couple of
template classes that were completely inline. The compiler still complained
about not finding "C" files for the templates, created thousands of little
files that needed to be linked in (most of which simply had typedefs in them or
dummy functions that were never called as far as I could tell), and regenerated
these files everytime the executable was linked even if *no* source code was
changed (I removed the executable and relinked immediately after linking just
to see if this would be true). Furthermore, I had to start linking like:
CC $(OBJS) $(LIBDIR)/lib/libname.a
instead of:
CC $(OBJS) -L$(LIBDIR) -lname
because the latter produced undefined symbols. Before telling me to get
another compiler, the only other compiler I could get for that machine didn't
even *have* templates and didn't even implement things like post
inc(dec)rement.
>The other point, is that my solution
>correctly called destructors, and the code I corrected did not.
The code you corrected was useless because it didn't call destructors.
>If you have
>another _safe_ and general approach that doesn't involve templates or
>language extensions, then I'd be very interested.
I don't necessarily agree that a language extension is needed. However, I
don't find template use a viable solution either. I haven't found the
situation very often and I have coded solutions manually each time when I
have.
>
>Cheers.
>--
>Kevlin A P Henney
>
> synonymicon is another word for thesaurus
Stephen Gevers
sg3235@shelob.sbc.com
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Tue, 9 Aug 1994 09:46:39 +0000 Raw View
In article <3265bp$krg@ritz.cec.wustl.edu>
sg3235@shelob.sbc.com "John Andrew Fingerhut" writes:
>In article <775917806snz@wslint.demon.co.uk>,
>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>Err, don't you like the idea of having the destructor called on
>>your object? Template instantiation is not a pain:
>
>It's not a pain if you don't want to work for an extra 20 minutes or longer
>during your link time. I refuse to use them until there isn't such an extra
>link time cost associated with them.
Unless I'm very much mistaken, the class I posted was small and inline.
There will be no link time overhead. The other point, is that my solution
correctly called destructors, and the code I corrected did not. If you have
another _safe_ and general approach that doesn't involve templates or
language extensions, then I'd be very interested.
Cheers.
--
Kevlin A P Henney
synonymicon is another word for thesaurus
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 9 Aug 1994 07:10:12 GMT Raw View
In article <JASON.94Aug8155118@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> >>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
|>
|> > This makes sense. I too find cleanup more elegant. But i still have
|> > something to say in favour of "after". "cleanup" does not allow the
|> > programmer to specify the order in which the "clean-up code" has to
|> > executed. "after" does. (I am assuming that the clean-up code will be
|> > decided by the compiler, probably following the order of the
|> > declarations.) It goes without sayng that we should alway write code
|> > without sequential dependencies, but sometimes we can't. In such
|> > situations only "after" would help.
|> 'cleanup' would work the same way cleanups for automatic variables do now;
|> they would be run in reverse lexical order. You can easily control the
|> ordering based on that.
Maybe I am missing the point, but to me that means that you have to
modify the order of the declarations to control the order of your cleanup
statements. I have assumed so far that C++ gives you extreme freedom with
declarations because that helps make your code more readable. (And liked that.)
I wouldn't want to loose that when I am using cleanup.
|> so I'd like to defer further
|> discussion at this point to people who have
Thanks for your views.
Cheers
Enrico.
Author: ball@Eng.Sun.COM (Mike Ball)
Date: 9 Aug 1994 15:37:31 GMT Raw View
In article en6@ritz.cec.wustl.edu, jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:
> The point is that I don't feel that templates are a viable solution to
> everyone until cfront based template schemes are refined or eliminated.
> And I am aware of at least one piece of hardware that isn't likely to get
> anything else.
And my point, which I should perhaps have made more explicit, is that you
shouldn't judge a language feature by the first attempt at implementing it.
The problem isn't with templates (though there have been many problems with
templates) but with a particular implementation. The cfront implementation
has some significant problems. OK, many first attempts do. Others learned
from that experiment and have made different implimentations (often with
their own problems) that avoid cfront's problems.
I think that templates are a viable solution to the original problem, the
implementation you are evidently forced to deal with just isn't a viable
solution to the template problem.
-Mike Ball-
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 9 Aug 1994 09:04:36 -0500 Raw View
In article <3268hf$pbp@engnews2.eng.sun.com>,
Mike Ball <ball@Eng.Sun.COM> wrote:
:In article krg@ritz.cec.wustl.edu, jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:
:> In article <775917806snz@wslint.demon.co.uk>,
:> Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
:> >Err, don't you like the idea of having the destructor called on
:> >your object? Template instantiation is not a pain:
:>
:> It's not a pain if you don't want to work for an extra 20 minutes or longer
:> during your link time. I refuse to use them until there isn't such an extra
:> link time cost associated with them.
:
:Perhaps his compiler doesn't have that link time cost.
:
:Not all of them do, you know.
Follow the thread back farther. The original poster was complaining that
templates are a pain and didn't like the proposed template solution. Kevlin's
compiler may not be a pain with regards to templates, but some compilers are,
including mine. My statement was backing up the original poster's statement.
The only two compilers I have tried templates on have been cfront based.
As I said in another post, I hope that Sun C++ 4.0 doesn't have the problems
that I have found in the cfont based compilers, but I haven't had a chance to
try it out.
The point is that I don't feel that templates are a viable solution to
everyone until cfront based template schemes are refined or eliminated.
And I am aware of at least one piece of hardware that isn't likely to get
anything else.
:
:Mike Ball
:SunSoft
:
Stephen Gevers
sg3235@shelob.sbc.com
Author: jf@cen.com (John Farley)
Date: 9 Aug 1994 14:11:07 GMT Raw View
>>>>>> jason@cygnus.com (Jason Merrill) writes:
>>>>> Ronald F Guilmette <rfg@netcom.com> writes:
>>> It's just that *some* of us were trained to avoid GOTO's like the plague.
>>What, didn't you read Knuth's response to Dijkstra's _Use of goto
>>considered harmful_? :)
As I recall, one of the other responses to Dijkstra was the proposal of
the comefrom statement (I can't find the reference, but I know that it
is here somewhere!). Comefrom seems to apply here:
void A::foo(void)
{
...
errorHere:
...
return;
comefrom (errorHere);
// error handling code goes here
return;
}
I hereby propose comefrom as a new C++ language feature to be considered
by THE COMMITTEE.
tongue.plantFirmly(cheek);
jfarley@cen.com -> johnFarley
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 9 Aug 1994 09:28:09 -0500 Raw View
In article <Cu7tuD.1xy@racal.demon.co.uk>,
Bill Petheram <billp@racal.demon.co.uk> wrote:
>
>What about
>
>f()
>
>{
>
> ... goto after; ....
>
> .... goto after; ....
>
> .... goto after;
>
>after:
>
> delete p1;
> delete p2; // or any other *trivial* clean up you have to do
> return;
>}
>
>--
>--
>Bill Petheram Email: billp@racal.demon.co.uk
>Racal Communications Systems Ltd, Tel: +44 344 483244
>Western Road, Bracknell, Berks, RJ12 1RG, UK. Fax: +44 344 860021
What about
f()
{
... goto after; ....
.... goto after; ....
.... goto after;
String test ("goto jumps around this!");
after:
delete p1;
delete p2; // or any other *trivial* clean up you have to do
return;
}
I thought that you couldn't goto around a variable declaration, but Sun C++ 4.0
only gives a warning. Even without an error on compile, Sun C++ 4.0 calls
the destructor for an object that was never created because goto jumped past
the creation. I don't think goto is a viable solution.
Stephen Gevers
sg3235@shelob.sbc.com
Author: kanze@us-es.sel.de (James Kanze US/ESC 60/3/164 #71425)
Date: 09 Aug 1994 15:06:56 GMT Raw View
In article <327a4k$8pk@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk
(Enrico Viali) writes:
|> In article <JASON.94Aug8155118@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> |> >>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
|> |> > This makes sense. I too find cleanup more elegant. But i still have
|> |> > something to say in favour of "after". "cleanup" does not allow the
|> |> > programmer to specify the order in which the "clean-up code" has to
|> |> > executed. "after" does. (I am assuming that the clean-up code will be
|> |> > decided by the compiler, probably following the order of the
|> |> > declarations.) It goes without sayng that we should alway write code
|> |> > without sequential dependencies, but sometimes we can't. In such
|> |> > situations only "after" would help.
|> |> 'cleanup' would work the same way cleanups for automatic variables do now;
|> |> they would be run in reverse lexical order. You can easily control the
|> |> ordering based on that.
|> Maybe I am missing the point, but to me that means that you have to
|> modify the order of the declarations to control the order of your cleanup
|> statements. I have assumed so far that C++ gives you extreme freedom with
|> declarations because that helps make your code more readable. (And liked that.)
|> I wouldn't want to loose that when I am using cleanup.
I think what Jason meant was that you would have to modify the order
of the cleanup statements in order to control the order of cleanup.
--
James Kanze email: kanze@lts.sel.alcatel.de
GABI Software, Sarl., 8 rue des Francs Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: gregor@netcom.com (Greg Colvin)
Date: Wed, 10 Aug 1994 01:11:18 GMT Raw View
For what it's worth, I plan on making a proposal of the following class, or
something close to it. A similar class which supported full garbage
collection was turned down at the last ISO meeting. Note that this is not
the most efficient implementation of reference counting, just, I hope, a
clear example.
////////////////////////////////////////////////////////////////////////
// Template for reference counted smart pointer.
// Pointers must be allocated via an operator new.
template<class X> class pointer {
X* px;
int* pi;
void init(X* p) { px = p; pi = new int; *pi = 1; }
void init(const pointer& r) { px = r.px; pi = r.pi; ++*pi; }
void drop() { if (--*pi == 0) delete px, delete pi; }
void grab(X* p) { if (px != p) drop(), init(p); }
void grab(const pointer& r) { if (px != r.px) drop(), init(r); }
public:
pointer(X* p=0) { init(p); }
pointer(const pointer& r) { init(r); }
~pointer() { drop(); }
pointer& operator=(X* p) { grab(p); return *this; }
pointer& operator=(const pointer& r) { grab(r); return *this; }
operator X*() const { return px; }
X* operator->() { return px; }
// template<class U> operator pointer<U>() { return pointer<U>(px,pi); }
// template<class D> pointer<D>dyn_cast() { return pointer<D>(dynamic_cast<D>(px),pi); }
}
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 10 Aug 1994 06:56:41 GMT Raw View
In article <Cu7tuD.1xy@racal.demon.co.uk>, billp@racal.demon.co.uk (Bill Petheram) writes:
|> In article <31qfa6$o5s@bull.saltfarm.bt.co.uk>,
> What about
|>
|> f()
|>
|> {
|>
|> ... goto after; ....
|>
|> .... goto after; ....
|>
|> .... goto after;
|>
|> after:
|>
|> delete p1;
|> delete p2; // or any other *trivial* clean up you have to do
|> return;
|> }
|>
|> --
|> --
|> Bill Petheram Email: billp@racal.demon.co.uk
|> Racal Communications Systems Ltd, Tel: +44 344 483244
|> Western Road, Bracknell, Berks, RJ12 1RG, UK. Fax: +44 344 860021
The main use of after/cleanup would be (obviously) cleaning up. So
you 'd want your clean up code executed when exceptions are thrown.
With gotos that does not happen.
Besides you can't always use gotos freely in C++.
(This has already been said in previous postings).
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 10 Aug 1994 07:01:09 GMT Raw View
In article <3282dk$en6@ritz.cec.wustl.edu>, jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:
|> Follow the thread back farther. The original poster was complaining that
|> templates are a pain and didn't like the proposed template solution.
My *main* complain is that the code you may want to excute at the exit of
a function is not only and always deleting a pointer. You may want to
check a postcondition,
empty a collection,
reinstall an old new_handler
write on the terminal "Yahoo!! I am exiting this function!!!" :-)
... whatever else...
(See my previous postings)
Author: jbuck@synopsys.com (Joe Buck)
Date: 10 Aug 1994 05:02:37 GMT Raw View
rfg@netcom.com (Ronald F. Guilmette) writes:
>But I would also agree that (totally independent of esthetic concerns)
>it would be one hell of a lot easier to have some facility in the
>language by which one could insure that some block finalization actions
>were invoked during *any* sort of exit from the block.
Excuse me if I'm missing something, but don't destructors already provide
such a capability? Any exit from the block, including exceptions, causes
destructors for automatic variables to be called.
>One thing that I do not think should be used to achieve block finalization
>is artificially introduced class types (with destructors) and associated
>artifically introduced objects of those types (as some have proposed).
>While this approach *would* work, it seems just too awfully messy to be
>considered as a serious candidate solution for the problem of block
>finalization (which is, after all, just a simple flow-of-control issue).
But using a class to represent cleanup can work well if it is designed
using the "resource allocation is initialization" approach advocated by
Stroustrup: constructors to represent acquisition of a resource,
destructors its freeing (and all necessary cleanup). Now it may be true
that a language extension might make some things clearer to beginners,
but I don't see that any semantic power is added. Generally, Ron, we
can count on you to speak against this type of unnecessary language
extension instead of advocating it.
If this kind of auto-cleanup is added, BTW, one natural way for compiler
writers to implement it into an existing compiler is as a destructor for
an object defined in the block, since it works in exactly the same way.
--
-- Joe Buck <jbuck@synopsys.com>
Posting from but not speaking for Synopsys, Inc.
***** Stamp out junk e-mail spamming! If someone sends you a junk e-mail
***** ad just because you posted in comp.foo, boycott their company.
Author: jason@cygnus.com (Jason Merrill)
Date: Wed, 10 Aug 1994 06:10:03 GMT Raw View
>>>>> Joe Buck <jbuck@synopsys.com> writes:
> If this kind of auto-cleanup is added, BTW, one natural way for compiler
> writers to implement it into an existing compiler is as a destructor for
> an object defined in the block, since it works in exactly the same way.
One difference is that a cleanup expression would have access to all of the
local names of the function, whereas the destructor for a local class can
only access static ones.
Jason
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 10 Aug 1994 11:12:37 -0500 Raw View
In article <JASON.94Aug9231003@deneb.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
>>>>>> Joe Buck <jbuck@synopsys.com> writes:
>
>> If this kind of auto-cleanup is added, BTW, one natural way for compiler
>> writers to implement it into an existing compiler is as a destructor for
>> an object defined in the block, since it works in exactly the same way.
>
>One difference is that a cleanup expression would have access to all of the
>local names of the function, whereas the destructor for a local class can
>only access static ones.
>
>Jason
Just to throw a wrench in things...a cleanup expression that only exists at
the end of a function would only work for things that had scope for the
function. For example:
int f(istream &i)
{
if (cond) {
Item *a = read_an_item (i);
. . .
if (cond2)
return -1;
}
cleanup {
delete a; // error...not in scope.
}
}
In other words, a cleanup/after would only work for items that have scope
for the entire function. Items declared within other blocks would have to
rely on the same old destructor method. I would think that any type of
cleanup extension would need to apply to all blocks, not just function blocks.
Furthermore, because the specific lines of code executed is generated by the
programmer, situations like this could happen:
int f (istream &i)
{
if (cond)
return;
Item *a = read_an_item (i);
. . .
cleanup {
delete a;
}
}
When this is handled with a destructor, the compiler knows whether or not
to invoke the destructor based on whether or not it has completed the
constructor. However, without further extensions, the programmer would not
be able to ascertain whether a resource really needed to be freed or not.
The following might solve the above mentioned problems:
A clenaup block can be declared anywhere in an existing block. Whenever a
block is exited, all cleanup blocks seen up to the point of the block exit
will be executed. For example:
int f (istream &i)
{
if (cond1)
return -1;
streampos pos = i.tellg ();
cleanup {
i.seekg (pos);
}
Item *a = read_an_item (i);
cleanup {
delete a;
}
if (cond2)
return -2;
if (cond3) {
Item *b = read_an_item (i);
cleanup {
delete b;
}
if (cond4)
return -4;
. . .
}
. . .
return 0;
}
Given this if cond1 is true:
no cleanups are executed.
if cond2 is true:
i.seekg(pos); delete a; are executed.
if cond3 is true then
if cond4 is true
i.seekg(pos); delete a; delete b; will be exected before the
return -4;
else
delete b; will be executed at the end of the if block
if cond3 is false or cond4 is false then
i.seekg(pos); delete a; are executed before the return 0;
I don't know if I really want something like ths added to the language, but
anything less would only be half a solution.
Stephen Gevers
sg3235@shelob.sbc.com
Author: jason@cygnus.com (Jason Merrill)
Date: Fri, 5 Aug 1994 20:24:45 GMT Raw View
>>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
> Is there a standard meaning for the term "smart pointer" ?
My guess would be: A class that encapsulates somehow the notion of a
pointer, typically providing operators -> and * and some way of converting
between it and built-in pointers. Any additional functionality is a bonus.
> |> >Anyway, how can you alway be sure that they are alway inlined? I can't!
> |> If your compiler ignores your inline directives, that's a quality of
> |> implementation issue. Instead of proposing a language extension to
> |> solve the problem, get a better quality implementation.
> Should a language be designed taking into account the optimization that the
> compilers will do? I do not the answer to this question. I guess this is
> a very relevant issue.
Well, that's what inline is. Inline is a suggestion that compilers perform
the optimization of expanding inline the function so marked each time it is
called. Whether or not a language *should* be so designed, it seems
apparent that C++ *has been* so designed.
Jason
Author: jason@cygnus.com (Jason Merrill)
Date: Fri, 5 Aug 1994 20:18:02 GMT Raw View
>>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
> In article <JASON.94Aug2162859@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
> |> which seems ***a lot** more maintainable than 'after', since the
> |> cleanup can be written in the same place as the allocation.
> It can be better than "after". I only thought about "after" in a hurry an did
> not evaluate it carefully but posted the idea of a swift clean up to have
> somebody else with more time and experience than me evaluating it; but I
> wonder why you did put that "a lot" which seems a bit exaggerated.
I don't remember putting so many stars around "a lot". I like 'cleanup'
better for exactly the reason stated above: it provides exactly the same
benefit as using a holder class, that being the ability to write the
allocation and the cleanup in the same place. I think that this is very
important to maintainable code.
It also looks trivial to implement. Being an implementor myself, that's a
plus...:)
Let me reiterate: my aesthetic reaction to 'after' was that it was an ugly
hack. Making one label somehow special is ugly, to my mind (at least
default only occurs in the company of other labels). Especially since it
occurs only at the end of the function, and may try to clean up things that
were never allocated:
main()
{
int *a;
while (1) a = new int[ULONG_MAX]; // eventually throws xalloc
int *b = new int;
after:
delete [] a;
delete b;
}
'cleanup', on the other hand, seems like a simple, elegant solution to the
problem.
> Why did you dislike "after" so much until a posting ago and now that a
> similar idea turns out to be already being considered you don't say that
> maybe the idea of a swift clean-up without acrobacies was not so bad?
> So, I ask, wheter it be "cleanup" or "after",: "was that idea so bad? so
> much worse of all the acrobacies? "
> Don't forget to mention that "clean-up" it is also more maintanable of
> all the strange, often not-working solutions that have been
> proposed,including yours.
Probably so. The main counterargument is still that when there are already
straightforward ways of doing something (and it looks like there will be
some form of smart pointer/holder class in the library if 'cleanup' is not
added), is it really necessary to extend the language to save people a few
keystrokes? The more distinct features there are in the language, the
harder it becomes to nail down exactly what the language is supposed to be.
Jason
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Sat, 6 Aug 1994 06:43:13 GMT Raw View
mec@shell.portal.com (Michael Edward Chastain) writes:
>Jason Merrill <jason@cygnus.com> wrote:
>> void foo ()
>> {
>> A* p = new A;
>> PtrDeleter dummy(p);
>> ...
>> }
>
>I don't get it.
[...]
>Am I missing some possible usage of '~PtrDeleter' beyond the
>example given?
Yes. Change the line
A* p = new A;
to
A* p = read_an_A(cin);
But `ArrayPtrDeleter', which does a `delete []' rather than a `delete',
would be a better example.
--
Fergus Henderson - fjh@munta.cs.mu.oz.au
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Sat, 6 Aug 1994 06:51:44 GMT Raw View
enrico@mround.bt.co.uk (Enrico Viali) writes:
>I had assumed that the term smart pointer was generally understood to
>refer to pointers that help with garbage collection (and finding suggestions
>about them strange until I saw what you meant).
>
>Is there a standard meaning for the term "smart pointer" ?
As I understand the term, smart pointers are user-defined classes which
act like pointers, but have some additional functionality not provided
by ordinary built-in pointers. This might be reference counting,
garbage collection, persistence, delegation, automatic deallocation, or
indeed any other functionality desired - it doesn't have to be garbage
collection.
>|> >Anyway, how can you alway be sure that they are alway inlined? I can't!
>|> If your compiler ignores your inline directives, that's a quality of
>|> implementation issue. Instead of proposing a language extension to
>|> solve the problem, get a better quality implementation.
>
>Should a language be designed taking into account the optimization that the
>compilers will do?
Yes, most definitely it should, IMHO.
--
Fergus Henderson - fjh@munta.cs.mu.oz.au
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sun, 7 Aug 1994 08:15:54 GMT Raw View
In article <CtoysA.7AD@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>In article <rfgCtLE6p.F54@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>>In article <312epq$5gd@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
>>>
>>>
>>>This is an old idea already present (in other form) in other languages (can't remember which).
>>>I was wondering about the utility of a keyword/special label at the end of a
>>>function such that the code after it is always executed before exiting.
>>
>>If you have some code that you want to ALWAYS have executed upon exit from
>>some scope, you *might* want to take a look at catch clauses. Those
>>*might* be suitable. Then again....
>
> Oh POOH!
>
> If you have code you want to always execute before
>destroying the outmost local variables of a function and
>exiting .. USE A GOTO STATEMENT!
You are right (of course) John.
It's just that *some* of us were trained to avoid GOTO's like the plague.
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sun, 7 Aug 1994 09:04:40 GMT Raw View
In article <9421415.7250@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
>enrico@duck.saltfarm.bt.co.uk (Enrico Viali) writes:
>>
>>The fact that I have to write an additional class.
>>With an after clause I do not have to write any extra code.
>
>One additional class? You're proposing a language extension to save
>yourself from having to write one little template class?
>Since this is obviously such a painful thing for you to do, I'll save
>you the trouble: you can use mine (attached at the end of this post).
>If it's really such a bother, then why not propose to put this class
>(or something like it) in the standard library, rather than propose a
>language extension?
Answer: Tradition.
(1/2 :-)
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: jason@cygnus.com (Jason Merrill)
Date: Sun, 7 Aug 1994 10:00:40 GMT Raw View
>>>>> Ronald F Guilmette <rfg@netcom.com> writes:
> It's just that *some* of us were trained to avoid GOTO's like the plague.
What, didn't you read Knuth's response to Dijkstra's _Use of goto
considered harmful_? :)
Jason
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Mon, 8 Aug 1994 10:16:52 +0000 Raw View
In article <JASON.94Aug5131802@deneb.cygnus.com>
jason@cygnus.com "Jason Merrill" writes:
[stuff deleted]
>Let me reiterate: my aesthetic reaction to 'after' was that it was an ugly
>hack. Making one label somehow special is ugly, to my mind (at least
>default only occurs in the company of other labels). Especially since it
>occurs only at the end of the function, and may try to clean up things that
>were never allocated:
>
>main()
>{
> int *a;
> while (1) a = new int[ULONG_MAX]; // eventually throws xalloc
>
> int *b = new int;
>
> after:
> delete [] a;
> delete b;
>}
>
>'cleanup', on the other hand, seems like a simple, elegant solution to the
>problem.
[stuff deleted]
Yes, after is particularly ugly and does not fit the language at all.
Since exceptions are related to blocks and not functions (goto labels are
the only kind of thing that have function scope), then any cleanup
mechanism should somehow be related to this. Following the example of
Modula-3 or even MS's hacked exception handling for NT, a generalised
exception structure would look something like:
try
{
...
}
catch(...)
{
...
}
finally
{
...
}
where the finally clause is always executed, ie. either after the try
clause in the absence of exceptions or after the catch clause in their
presence. So normal functions that required specifc cleanup and did not
use smart pointers or other pointer owner objects would be written as
void fn()
{
try
{
...
}
finally
{
...
}
}
For my money ($0.02), this is clearer than other cleanup extensions.
Whether we actually want it in the language is another question :-)
--
Kevlin A P Henney
synonymicon is another word for thesaurus
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 8 Aug 1994 07:49:27 GMT Raw View
|> > Should a language be designed taking into account the optimization that the
|> > compilers will do? I do not ***know the answer to this question. I guess
|> > this is a very relevant issue.
|>
|> Well, that's what inline is. Inline is a suggestion that compilers perform
|> the optimization of expanding inline the function so marked each time it is
|> called. Whether or not a language *should* be so designed, it seems
|> apparent that C++ *has been* so designed.
|>
|> Jason
I disagree.
I can't see any feature of C++ that is what it is because of the possibility of
declaring a function inline. Anyway I find this subject very interesting so
further comments are most welcome.
***
PS sorry for the bad typing in my previous message.
Enrico.
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 8 Aug 1994 07:57:18 GMT Raw View
|> I don't think that is a good answer. I want to program in C++. In fact, I
|> do program in C++. I haven't gotten used to template instantiation and I
|> don't intend on using templates until such time as compiling with them doesn't
|> take have the day and 3/4 of my machines resources. Templates are a good idea
|> with a faulty implementation. I haven't had the chance to try out templates
|> on Sun C++ 4.0 yet. Maybe they've sped things up by now.
The implementation on the HPs is discouriging too.
Enrico.
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 8 Aug 1994 09:29:25 GMT Raw View
In article <rfgCu5oAJ.61J@netcom.com>, rfg@netcom.com (Ronald F. Guilmette) writes:
|> > If you have code you want to always execute before
|> >destroying the outmost local variables of a function and
|> >exiting .. USE A GOTO STATEMENT!
|>
|> You are right (of course) John.
|>
|> It's just that *some* of us were trained to avoid GOTO's like the plague.
Yes, I confess, I am an idiot that blindly follows what was taught without
any originality or discernment.
Please spend a minute considering this:
"After" or "cleanup" code would clearly be executed when exceptions are thrown.
GOTOs wouldn't.
and possibly comment.
Thinking about GOTO s was the first thing I made. Unfortunately my compiler too
had been trained not to be too keen about GOTOs (HP C++ 3.4).
I can't certainly maintain that we need "cleanup" or "after" because *my*
compiler does not fully implements GOTO's but I stil like that idea
(I will not say why again now but will post a sort of summary when I have time)
If you can shed any light on this please do it.
/disc/duck0/evdata/inhouse/model/hmm/parts[342]>> make quickdebug
make 'ROOT=' -f Makefile load\
'VERSION_COMPFLAGS = -g' \
'VERSION_DEFINES = -DTRACE -DMODEL_TEST -DRTINVAR ' \
'LIBNAME = libhmmparts.deb'
/usr/softbench/bin/CC -g
-DTRACE -DMODEL_TEST -DRTINVAR -DFLOAT_SCORE -DUSE_DEFAULT_ALLOCATOR_FOR_PATH -I/inhouse -I/inhouse/include -I/usr/local/rogue -c Fs2Models.C
CC: "Fs2Models.C", line 1222: sorry, not implemented: label in block
with destructors (2048) *** Error code 1
The code follows
//=============================================================================
RTBool testCheckConnection(RTBool, ostream & out)
//=============================================================================
{
FS2_TRACE("testCheckConnection(RTBool interactive)");
Models som;
som.setModelsColl(createMCoreHmmDatas(4));
RTBool ret = 1;
if (!som.checkConnection()) // here the connections should be ok
{
out << "\ntestCheckConnection FAILED at file , line : "
<< __FILE__ << " , " << __LINE__ << endl;
goto cleanup;
}
//objects that do not point to other objects are used to make things simple
partsCollIterator * it;
MMean * meanPtr;
it = new partsCollIterator(*som.mMeans); // disconnect the first mean
meanPtr = CAST((*it)(),MMean);
assert(som.mMeans->remove(meanPtr));
delete it;
MCovar * covarPtr;
it = new partsCollIterator(*som.mCovars); // disconnect the first mode
covarPtr = CAST((*it)(),MCovar);
assert(som.mCovars->remove(covarPtr));
delete it;
if (som.checkConnection()) // here the connections are not good
{
out << "\ntestCheckConnection FAILED at file , line : "
<< __FILE__ << " , " << __LINE__ << endl;
goto cleanup;
}
som.connect();
if (!som.checkConnection())
{
out << "\ntestCheckConnection FAILED at file , line : "
<< __FILE__ << " , " << __LINE__ << endl;
goto cleanup;
}
cleanup:
som.releaseAndDestroyModels();
return 1;
}
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 8 Aug 1994 10:03:03 GMT Raw View
In article <rfgCu5qJs.810@netcom.com>, rfg@netcom.com (Ronald F. Guilmette) writes:
|> In article <9421415.7250@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
|> >enrico@duck.saltfarm.bt.co.uk (Enrico Viali) writes:
|> >>
|> >>The fact that I have to write an additional class.
|> >>With an after clause I do not have to write any extra code.
|> >
|> >One additional class? You're proposing a language extension to save
|> >yourself from having to write one little template class?
|> >Since this is obviously such a painful thing for you to do, I'll save
|> >you the trouble: you can use mine (attached at the end of this post).
|> >If it's really such a bother, then why not propose to put this class
|> >(or something like it) in the standard library, rather than propose a
|> >language extension?
|>
|> Answer: Tradition.
Deleting pointers is not the only thing you could need at the exit of a
function.
You could want to check a postcondition or release all the items in a
collection.
I guess you would define "smart preconditions" "smart collections" Etc.
More than one extra class.
Author: kanze@us-es.sel.de (James Kanze US/ESC 60/3/164 #71425)
Date: 08 Aug 1994 15:43:50 GMT Raw View
In article <JASON.94Aug7030040@deneb.cygnus.com> jason@cygnus.com
(Jason Merrill) writes:
|> >>>>> Ronald F Guilmette <rfg@netcom.com> writes:
|> > It's just that *some* of us were trained to avoid GOTO's like the plague.
|> What, didn't you read Knuth's response to Dijkstra's _Use of goto
|> considered harmful_? :)
Which, in fact, doesn't really contradict what Dijkstra is saying.
If you analyse the uses Knuth accepts for goto's (in the article
cited), they all correspond to optimizations. When Knuth was writing,
this was very relevant, but today, all of the instances he actually
shows would be caught by a typical optimizing compiler.
On the other hand, Knuth does use goto in some of his more recent code
(TeX, for example). But in all of the cases I've seen, it is being
used to emulate exceptions:-).
--
James Kanze email: kanze@lts.sel.alcatel.de
GABI Software, Sarl., 8 rue des Francs Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 8 Aug 1994 16:51:33 GMT Raw View
In article <JASON.94Aug5131802@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> >>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
|>
|> > In article <JASON.94Aug2162859@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> I like 'cleanup'
|> better for exactly the reason stated above: it provides exactly the same
|> benefit as using an holder class, that being the ability to write the
|> allocation and the cleanup in the same place. I think that this is very
|> important to maintainable code.
|>
|> It also looks trivial to implement. Being an implementor myself, that's a
|> plus...:)
This makes sense. I too find cleanup more elegant.
But i still have something to say in favour of "after".
"cleanup" does not allow the programmer to specify the order in which
the "clean-up code" has to executed.
"after" does.
(I am assuming that the clean-up code will be decided by the compiler, probably
following the order of the declarations.)
It goes without sayng that we should alway write code without sequential
dependencies, but sometimes we can't.
In such situations only "after" would help.
|> Let me reiterate: my aesthetic reaction to 'after' was that it was an ugly
|> hack. Making one label somehow special is ugly, to my mind (at least
Please let's distinguish bwtween the idea and its "form".
Making after a special label was only one of the possibilities.
after could be a keyword or, if we don't want to increase the number of
keywords, we could think about something like
~<function_name>
that is
f()
{
~f
}
|> 'cleanup', on the other hand, seems like a simple, elegant solution to the
|> problem.
"after" and "cleanup" are to attempts to implement the same idea (give the programmer
the possibility of writing code to be executed after return).
Only the syntax changes.
One can have aesthetical preferences but not say that one of the two is
a good idea and the other a bad one.
Let's call that idea "user contrallable exit code" (sounds very ugly but can't find
anything better) UCEC for short.
Let's forget the theme "after" vs. "cleanup"; and compare "resource acquisition
.." (RAI from now on) with UCEC.
Probably I am biased because after is my idea but still find hard
to accept that other people are not bo(the)red about using RAI.
Have a look at this code and tell me what you think.
//****************************************************************************
RTBool setOfTrParts::loadTrParts(const char *const FName)
/******************************************************************************
This function must provide an open file/stream *with the file pointer
correctly positioned* to the functions it calls.
A manual adjustment is necessary for the file format.
=============================================================================*/
{
FS2_TRACE("setOfTrParts::loadTrParts(const char *const FName)");
PreCond(GetNumTrModels() == 0);
// ------ I don't like this, but is still the best option -------------
struct dummy
{
dummy(setOfTrParts * p) : x(p)
{ old_new_handler = set_new_handler(Fs2NewHandler);}
~dummy() { set_new_handler(old_new_handler);
PostCond(x->trHmmAccs->entries() > 0);
x->connect(); }
setOfTrParts * x;
void (*old_new_handler) (void);
} dummyobject(this);
// -------------------------------------------------------------------
ifstream f(FName);
if (!f.good())
{
SRecWarning("setOffParts::loadParts()","!f.good()");
return 0;
}
if (!header.readHeader(f))
return 0;
switch (header.GetFormat())
{
case ASCII : return loadFromASCIIStrm(f);
case BIN : return loadFromBinStrm(f);
case RWFILE : {
long offset = f.tellg();
f.close();
RWFile rwf(FName);
rwf.SeekTo(offset); // skip the header
return loadFromFile(rwf);
}
default : SRecWarning("setOfTrParts::loadParts()","unknown format");
return 0;
}
}
|> > Why did you dislike "after" so much until a posting ago and now that a
|> > similar idea turns out to be already being considered you don't say that
|> > maybe the idea of a swift clean-up without acrobacies was not so bad?
|> > So, I ask, wheter it be "cleanup" or "after",: "was that idea so bad? so
|> > much worse of all the acrobacies? "
|> Probably so.
|> The main counterargument is still that when there are already
|> straightforward ways of doing something (and it looks like there will be
|> some form of smart pointer/holder class in the library if 'cleanup' is not
|> added), is it really necessary to extend the language to save people a few
|> keystrokes?
(When we started the discussion the possibilty that the standard library would
include smart pointers Etc. had not been presented.)
I believe that cleaning up is not always just a matter of deleting pointers
(just look at the code above).
This puts smart pointers completely out of the game.
Only RAI remains.
Probably is just a matter of personal preferences, but having an extra class,
however trivial, and a dummy object, like in the code above, is not something
I consider straightforward and, frankly, I wonder how you can find it so.
|> The more distinct features there are in the language, the
|> harder it becomes to nail down exactly what the language is supposed to be.
This is true. But "after" or "cleanup" will not bring deep changes to the
semantics of the language, they will just give extra control to the programmer.
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Mon, 8 Aug 1994 19:08:18 GMT Raw View
In article <324ttl$a8g@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
>In article <rfgCu5oAJ.61J@netcom.com>, rfg@netcom.com (Ronald F. Guilmette) writes:
>
>|> > If you have code you want to always execute before
>|> >destroying the outmost local variables of a function and
>|> >exiting .. USE A GOTO STATEMENT!
>|>
>|> You are right (of course) John.
>|>
>|> It's just that *some* of us were trained to avoid GOTO's like the plague.
>
>Yes, I confess, I am an idiot that blindly follows what was taught without
>any originality or discernment.
>
>Please spend a minute considering this:
>
>"After" or "cleanup" code would clearly be executed when exceptions are thrown.
>GOTOs wouldn't.
>
>and possibly comment.
My only comment is that *you* are right also.
It's true that if you are diligent enough, you can achieve just about
anything you want (in the way of flow-of-control) using GOTOs. So in
that (limited) sense, John was right.
But I would also agree that (totally independent of esthetic concerns)
it would be one hell of a lot easier to have some facility in the
language by which one could insure that some block finalization actions
were invoked during *any* sort of exit from the block.
Earlier, I noted that `catch()' or perhaps `catch(...)' might be hijacked
for exactly this purpose. (And by the way, X3J16/WG21 is discussing
various alternative solutions to the block finalization problem as we
speak.)
One thing that I do not think should be used to achieve block finalization
is artificially introduced class types (with destructors) and associated
artifically introduced objects of those types (as some have proposed).
While this approach *would* work, it seems just too awfully messy to be
considered as a serious candidate solution for the problem of block
finalization (which is, after all, just a simple flow-of-control issue).
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 8 Aug 1994 15:42:33 -0500 Raw View
In article <775917806snz@wslint.demon.co.uk>,
Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>Err, don't you like the idea of having the destructor called on
>your object? Template instantiation is not a pain:
It's not a pain if you don't want to work for an extra 20 minutes or longer
during your link time. I refuse to use them until there isn't such an extra
link time cost associated with them.
>--
>Kevlin A P Henney
>
> synonymicon is another word for thesaurus
Stephen Gevers
sg3235@shelob.sbc.com
Author: ball@Eng.Sun.COM (Mike Ball)
Date: 8 Aug 1994 21:36:47 GMT Raw View
In article krg@ritz.cec.wustl.edu, jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut) writes:
> In article <775917806snz@wslint.demon.co.uk>,
> Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
> >Err, don't you like the idea of having the destructor called on
> >your object? Template instantiation is not a pain:
>
> It's not a pain if you don't want to work for an extra 20 minutes or longer
> during your link time. I refuse to use them until there isn't such an extra
> link time cost associated with them.
Perhaps his compiler doesn't have that link time cost.
Not all of them do, you know.
Mike Ball
SunSoft
Author: jason@cygnus.com (Jason Merrill)
Date: Mon, 8 Aug 1994 20:51:56 GMT Raw View
>>>>> Kevlin Henney <kevlin@wslint.demon.co.uk> writes:
> try
> {
> ...
> }
> catch(...)
> {
> ...
> }
> finally
> {
> ...
> }
This also came up in the discussion; I believe that this extension has been
considered and rejected by the committee. It may yet be accepted, I
suppose.
Jason
Author: jason@cygnus.com (Jason Merrill)
Date: Mon, 8 Aug 1994 22:51:18 GMT Raw View
>>>>> Enrico Viali <enrico@mround.bt.co.uk> writes:
> This makes sense. I too find cleanup more elegant. But i still have
> something to say in favour of "after". "cleanup" does not allow the
> programmer to specify the order in which the "clean-up code" has to
> executed. "after" does. (I am assuming that the clean-up code will be
> decided by the compiler, probably following the order of the
> declarations.) It goes without sayng that we should alway write code
> without sequential dependencies, but sometimes we can't. In such
> situations only "after" would help.
'cleanup' would work the same way cleanups for automatic variables do now;
they would be run in reverse lexical order. You can easily control the
ordering based on that.
> Have a look at this code and tell me what you think.
> struct dummy
> {
> dummy(setOfTrParts * p) : x(p)
> { old_new_handler = set_new_handler(Fs2NewHandler);}
> ~dummy() { set_new_handler(old_new_handler);
> PostCond(x->trHmmAccs->entries() > 0);
> x-> connect(); }
> setOfTrParts * x;
> void (*old_new_handler) (void);
> } dummyobject(this);
It's probably possible to make this prettier by using macros. I've never
really had to deal with this problem myself, so I'd like to defer further
discussion at this point to people who have; there are certainly people on
the X3J16 library mailing list that seem to have been using holder classes
happily; are any of them lurking here?
> |> The more distinct features there are in the language, the
> |> harder it becomes to nail down exactly what the language is supposed to be.
> This is true. But "after" or "cleanup" will not bring deep changes to the
> semantics of the language, they will just give extra control to the
> programmer.
Probably true.
Jason
Author: billp@racal.demon.co.uk (Bill Petheram)
Date: Mon, 8 Aug 1994 12:11:00 +0000 Raw View
In article <31qfa6$o5s@bull.saltfarm.bt.co.uk>,
Enrico Viali <enrico@mround.bt.co.uk> wrote:
>
>Again i prefer
>
>f()
>
>{
>
> ... return ....
>
> .... return ....
>
> .... return
>
>after
>
> delete p1;
> delete p2; // or any other *trivial* clean up you have to do
>}
>
What about
f()
{
... goto after; ....
.... goto after; ....
.... goto after;
after:
delete p1;
delete p2; // or any other *trivial* clean up you have to do
return;
}
--
--
Bill Petheram Email: billp@racal.demon.co.uk
Racal Communications Systems Ltd, Tel: +44 344 483244
Western Road, Bracknell, Berks, RJ12 1RG, UK. Fax: +44 344 860021
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 9 Aug 1994 06:58:37 GMT Raw View
In article <776341012snz@wslint.demon.co.uk>, kevlin@wslint.demon.co.uk (Kevlin Henney) writes:
|> Yes, after is particularly ugly and does not fit the language at all.
|> Since exceptions are related to blocks and not functions (goto labels are
|> the only kind of thing that have function scope), then any cleanup
|> mechanism should somehow be related to this. Following the example of
We are not talking about after has a substitute for exceptions but just
observing that GOTOs would not harmonize (clean) well with exceptions, after/cleanup would.
Besides if you think a bit about it you will see that C++ exceptions rely on
stack unwinding, there is a strong procedural component in them.
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 1 Aug 1994 01:11:04 GMT Raw View
enrico@mround.bt.co.uk (Enrico Viali) writes:
>The "resource acquisition as initialization" technique is often too boring
>for trivial cases like deleting 2,3 pointers and imposes too much overhead.
What's so boring about using a template smart pointer class?
What's the overhead, if the constructor and destructor are inline?
>xxx f(......)
>{
NewPtr<Foo> p1 = new Foo(...);
NewPtr<Bar> p2 = new Bar(...);
> // do whatever you want
> ....
>}
--
Fergus Henderson - fjh@munta.cs.mu.oz.au
Author: enrico@duck.saltfarm.bt.co.uk (Enrico Viali)
Date: 1 Aug 1994 11:13:01 +0100 Raw View
Author: jason@cygnus.com (Jason Merrill)
Date: Mon, 1 Aug 1994 20:40:40 GMT Raw View
>>>>> Enrico Viali <enrico@duck.saltfarm.bt.co.uk> writes:
> I also think that if you use smart pointers you have to use
> reference counting; that menas extra space and that you pointers
> operation are slowed down by the updating of the "count"field.
You don't have to use reference-counting smart pointers. Hey, here's a
class for ya:
class PtrDeleter {
void *p;
public:
PtrDeleter (void *ptr) { p = ptr; }
~PtrDeleter () { delete p; }
};
void foo ()
{
A* p = new A;
PtrDeleter dummy(p);
...
}
> Besides template instantiation is a pain. (and if you don't use
> you have to write more than 1 class; even more boring...)
No you don't; just use void*.
> Anyway, how can you alway be sure that they are alway inlined? I can't!
> Inline is just a suggestion ignored in most of the cases.
If your compiler can't inline the above (or doesn't even when optimizing)
you have a poor compiler.
Jason
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 2 Aug 1994 05:12:01 GMT Raw View
enrico@duck.saltfarm.bt.co.uk (Enrico Viali) writes:
>From fjh@munta.cs.mu.OZ.AU (Fergus Henderson):
>> enrico@mround.bt.co.uk (Enrico Viali) writes:
>>
>>>The "resource acquisition as initialization" technique is often too boring
>>>for trivial cases like deleting 2,3 pointers and imposes too much overhead.
>>
>> What's so boring about using a template smart pointer class?
>
>The fact that I have to write an additional class.
>With an after clause I do not have to write any extra code.
One additional class? You're proposing a language extension to save
yourself from having to write one little template class?
Since this is obviously such a painful thing for you to do, I'll save
you the trouble: you can use mine (attached at the end of this post).
If it's really such a bother, then why not propose to put this class
(or something like it) in the standard library, rather than propose a
language extension?
>I also think that if you use smart pointers you have to use
>reference counting; that menas extra space and that you pointers
>operation are slowed down by the updating of the "count"field.
No, you don't need to use reference counting.
>Besides template instantiation is a pain.
Welcome to C++! If you want to program in C++, you're going to
have to get used to template instantiation.
>> What's the overhead, if the constructor and destructor are inline?
>>
>>>xxx f(......)
>>>{
>> NewPtr<Foo> p1 = new Foo(...);
>> NewPtr<Bar> p2 = new Bar(...);
>>> // do whatever you want
>>> ....
>>>}
>
>As said above, referenxce counting involves space and speed overhead.
>Anyway, how can you alway be sure that they are alway inlined? I can't!
>Inline is just a suggestion ignored in most of the cases.
If your compiler ignores your inline directives, that's a quality of
implementation issue. Instead of proposing a language extension to
solve the problem, get a better quality implementation.
--- newptr.h ------- cut here -------------------------------------------------
//-----------------------------------------------------------------------------
//
// Class NewPtr<T>.
//
// A pointer to a dynamically allocated object, which will be
// automatically deleted by the destructor for NewPtr<T>.
//
#ifndef NEWPTR_H
#define NEWPTR_H
template <class T>
class NewPtr {
private:
void operator =(const NewPtr<T> &); // declared but not defined
NewPtr(const NewPtr<T> &); // declared but not defined
T* ptr;
public:
NewPtr(T* the_ptr); // the_ptr must have been dynamically allocated
T* operator->() const;
T& operator*() const;
operator T*() const;
~NewPtr();
};
template <class T>
inline
NewPtr<T>::NewPtr(T* the_ptr)
: ptr(the_ptr)
{}
template <class T>
inline T*
NewPtr<T>::operator->() const
{
return ptr;
}
template <class T>
inline T&
NewPtr<T>::operator*() const
{
return *ptr;
}
template <class T>
inline
NewPtr<T>::operator T *() const
{
return ptr;
}
template <class T>
inline
NewPtr<T>::~NewPtr() {
delete ptr;
}
#endif // NEWPTR_H
--- test.cxx ------- cut here -------------------------------------------------
#include <iostream.h>
#include "newptr.h"
void f(int *p) { ++*p; }
void g(double *p) { ++*p; }
int main() {
NewPtr<int> p1 (new int);
NewPtr<double> p2 (new double);
*p1 = 0;
*p2 = 0.0;
f(p1);
g(p2);
cout << "*p1 = " << *p1 << endl;
cout << "*p2 = " << *p2 << endl;
return 0;
}
--
Fergus Henderson - fjh@munta.cs.mu.oz.au
Author: daniels@biles.com (Brad Daniels)
Date: Tue, 2 Aug 1994 15:26:52 GMT Raw View
In article <JASON.94Aug1134040@deneb.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
>>>>>> Enrico Viali <enrico@duck.saltfarm.bt.co.uk> writes:
>
>> I also think that if you use smart pointers you have to use
>> reference counting; that menas extra space and that you pointers
>> operation are slowed down by the updating of the "count"field.
>
>You don't have to use reference-counting smart pointers. Hey, here's a
>class for ya:
>
>class PtrDeleter {
> void *p;
>public:
> PtrDeleter (void *ptr) { p = ptr; }
> ~PtrDeleter () { delete p; }
>};
>
>void foo ()
>{
> A* p = new A;
> PtrDeleter dummy(p);
> ...
>}
>
>> Besides template instantiation is a pain. (and if you don't use
>> you have to write more than 1 class; even more boring...)
>
>No you don't; just use void*.
I'm not even sure it's legal to delete a void *. I'm very sure the
dtor of the object won't get called. PtrDeleter has to be a template
class if you choose to take that approach.
Also, the code you wrote in foo() is roughly equivalent to having
a local variable of class A. What if you want the object to persist
until everyone's through with it? You need reference counting.
- Brad
------------------------------------------------------------------------------
+ Brad Daniels | If all you've got is a screwdriver, pretty +
+ Biles and Associates | soon every problem starts looking like a +
+ These are my views, not B&A's | nail. Then you're screwed... +
------------------------------------------------------------------------------
Author: jason@cygnus.com (Jason Merrill)
Date: Tue, 2 Aug 1994 23:28:59 GMT Raw View
>>>>> Brad Daniels <daniels@biles.com> writes:
> I'm not even sure it's legal to delete a void *.
It is.
> I'm very sure the dtor of the object won't get called. PtrDeleter has to
> be a template class if you choose to take that approach.
True.
> Also, the code you wrote in foo() is roughly equivalent to having
> a local variable of class A. What if you want the object to persist
> until everyone's through with it? You need reference counting.
Well, yes. If you want to count references, you need reference counting.
But having the cleanup for an object delete the pointer is semantically
equivalent to deleting the pointer in an 'after' block; if you want to wait
until everyone's done with it, 'after' won't work for you either.
This discussion has migrated to the X3J16 mailing lists; on one of them,
the proposal was recently made to extend the language to allow code like
main()
{
A* ap = new A;
cleanup { delete ap; }
...
}
which seems a lot more maintainable than 'after', since the cleanup can be
written in the same place as the allocation.
Jason
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Wed, 3 Aug 1994 08:11:27 GMT Raw View
In article <JASON.94Aug2162859@deneb.cygnus.com> jason@cygnus.com (Jason Merrill) writes:
>>>>>> Brad Daniels <daniels@biles.com> writes:
>
>> I'm not even sure it's legal to delete a void *.
>
>It is.
I'm not so sure about that Jason.
I believe there's a rule that says that the static type of the pointer
you delete must be the same as the static type of the pointer that was
actually yielded (in the first instance, before any conversions) by some
previous call to new.
Since you cannot new a `void' (can you?) the implication is that you
cannot do a delete on a void*.
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: mec@shell.portal.com (Michael Edward Chastain)
Date: 3 Aug 1994 09:24:23 GMT Raw View
In article <JASON.94Aug1134040@deneb.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
> You don't have to use reference-counting smart pointers. Hey, here's a
> class for ya:
>
> class PtrDeleter {
> void *p;
> public:
> PtrDeleter (void *ptr) { p = ptr; }
> ~PtrDeleter () { delete p; }
> };
>
> void foo ()
> {
> A* p = new A;
> PtrDeleter dummy(p);
> ...
> }
I don't get it.
How is this different from:
void foo ()
{
A p;
...
}
Am I missing some possible usage of '~PtrDeleter' beyond the
example given?
Michael Chastain
mec@shell.portal.com
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Wed, 3 Aug 1994 12:43:26 +0000 Raw View
In article <JASON.94Aug1134040@deneb.cygnus.com>
jason@cygnus.com "Jason Merrill" writes:
>You don't have to use reference-counting smart pointers. Hey, here's a
>class for ya:
>
>class PtrDeleter {
> void *p;
>public:
> PtrDeleter (void *ptr) { p = ptr; }
> ~PtrDeleter () { delete p; }
>};
>
>void foo ()
>{
> A* p = new A;
> PtrDeleter dummy(p);
> ...
>}
>
>> Besides template instantiation is a pain. (and if you don't use
>> you have to write more than 1 class; even more boring...)
>
>No you don't; just use void*.
Err, don't you like the idea of having the destructor called on
your object? Template instantiation is not a pain:
template<class Type> class PtrDeleter
{
public:
PtrDeleter( Type *to_delete ) : p( to_delete ) {}
~PtrDeleter() { delete p; }
private:
Type *p;
PtrDeleter( const PtrDeleter<Type> & );
PtrDeleter<Type> &operator=( const PtrDeleter<Type> & );
};
...
void foo ()
{
A* p = new A;
PtrDeleter<A> dummy(p);
...
}
One class, no problems - don't use void *, use C++ ;-)
--
Kevlin A P Henney
synonymicon is another word for thesaurus
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 4 Aug 1994 10:18:46 GMT Raw View
In article <JASON.94Aug1134040@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> >>>>> Enrico Viali <enrico@duck.saltfarm.bt.co.uk> writes:
|>
|> > I also think that if you use smart pointers you have to use
|> > reference counting; that menas extra space and that you pointers
|> > operation are slowed down by the updating of the "count"field.
|>
|> You don't have to use reference-counting smart pointers. Hey, here's a
|> class for ya:
|>
|> class PtrDeleter {
|> void *p;
|> public:
|> PtrDeleter (void *ptr) { p = ptr; }
|> ~PtrDeleter () { delete p; }
|> };
|>
|> void foo ()
|> {
|> A* p = new A;
|> PtrDeleter dummy(p);
|> ...
|> }
|>
|> > Besides template instantiation is a pain. (and if you don't use
|> > you have to write more than 1 class; even more boring...)
|>
|> No you don't; just use void*.
Sorry Jason but I don't like void.
I do not have time now to look at the stuff above and the ARM in detail but I suspect there coud be problems when deleting the "smart? but "void!"" pointer.
***************************************************************************
I want to state again that my wondering about the usefulness and the feasability
of an "after" clause originated by the fact that ***for trivial cases***
I did not want the extra typing and extra class involved by the resource acquisition as initialization or more acrobatic techniques.
Again i prefer
f()
{
... return ....
.... return ....
.... return
after
delete p1;
delete p2; // or any other *trivial* clean up you have to do
}
to
f()
{
.....
delete p1;
delete p2;
return
.....
delete p1;
delete p2;
return...
.....
delete p1;
delete p2;
return
}
and all the acrobatic stuff mentioned so far.
I have solved the problem of the extra typing (and risk of errors),
in the situation that made me wonder about the utility and feasability
of an after close in the following, unsatisfyng for my taste, way:
#define CLEANUP_AND_RETURN(x) \
delete p1;
delete p2;
return(x)
f()
{
...............
CLEANUP_AND_RETURN(0);
Etc
}
This reduces typing and the risk of errors when modifying the clean up
but duplicates code.
"after" WOULDN'T.
ALL THE SMART SOLUTIONS SUGGEST CAUSE AN INCREASE IN CODE!!!
I DO NOT WANT THAT!!!
I WANT SIMPLICITY, NOT GENIALITY AN COMPLEXITY, (AND LESS TYPING)!
The comments I was expecting where mainly about how an "after" clause could
be implemented; which problems it would pose to compiler writers, wheter
it is actually possibkle to implement it.
ENRICO.
Author: jason@cygnus.com (Jason Merrill)
Date: Thu, 4 Aug 1994 01:09:06 GMT Raw View
>>>>> Ronald F Guilmette <rfg@netcom.com> writes:
> In article <JASON.94Aug2162859@deneb.cygnus.com> jason@cygnus.com (Jason Merrill) writes:
>>>>>>> Brad Daniels <daniels@biles.com> writes:
>>
>>> I'm not even sure it's legal to delete a void *.
>>
>> It is.
> I'm not so sure about that Jason.
> I believe there's a rule that says that the static type of the pointer
> you delete must be the same as the static type of the pointer that was
> actually yielded (in the first instance, before any conversions) by some
> previous call to new.
That only applies if the object pointed to has a destructor, and even then
the code is well-formed (but ill-defined).
Jason
Author: "Kevin Cooney" <cooney@vnet.ibm.com>
Date: Thu, 4 Aug 1994 19:24:46 GMT Raw View
There is a problem with template smart pointers. If
B is inherited from A:
void
foo( Handle<A> );
..
Handle<B> a = new A;
foo( a ); // doesn't compile
The "after" suggestion looks messy. Something I might like to see
would be a smart pointer in C++, that would handle the reference counts
for you. To work, a smart pointer couldn't be automatically casted to
a regular pointer, or vise-versa, so you'd need a special version of new:
A* smart foo( ... )
{
...
return smart new B( ... );
}
A* smart a = foo( ... );
A* a2 = a; // illegal
A* smart a3 = a2; // also illegal
A& smart a4 = *a; // why not? :)
I don't like the idea of making the language more complicated then it
is, but I don't think you should have to worry about memory allocation
in an OO language, either. If your framework involves returning base
classes to hidden derived-classes, there is no pretty solution. I'd
love to see a robust template solution.
-Kevin
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Kevin W. Cooney |
cooney+@cmu.edu | http://www.contrib.andrew.cmu.edu:8001/usr/kc2z/home
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 4 Aug 1994 12:06:11 GMT Raw View
In article <JASON.94Aug2162859@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
|> This discussion has migrated to the X3J16 mailing lists; on one of them,
|> the proposal was recently made to extend the language to allow code like
|>
|> main()
|> {
|> A* ap = new A;
|> cleanup { delete ap; }
|>
|> ...
|> }
So I am not the only one who likes simplicity.
|> which seems ***a lot** more maintainable than 'after', since the cleanup can
|> be written in the same place as the allocation.
It can be better than "after". I only thought about "after" in a hurry an did
not evaluate it carefully but posted the idea of a swift clean up to have
somebody else with more time and experience than me evaluating it; but I
wonder why you did put that "a lot" which seems a bit exaggerated. Why did you
dislike "after" so much until a posting ago and now that a similar idea turns
out to be already being considered you don't say that maybe the idea of a
swift clean-up without acrobacies was not so bad?
So, I ask, wheter it be "cleanup" or "after",: "was that idea so bad? so much
worse of all the acrobacies? "
Don't forget to mention that "clean-up" it is also more maintanable of all the strange, often not-working solutions that have been proposed,including yours.
Enrico.
Author: jaf3@ritz.cec.wustl.edu (John Andrew Fingerhut)
Date: 5 Aug 1994 15:40:51 -0500 Raw View
In article <9421415.7250@mulga.cs.mu.oz.au>,
Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
>enrico@duck.saltfarm.bt.co.uk (Enrico Viali) writes:
>>Besides template instantiation is a pain.
>
>Welcome to C++! If you want to program in C++, you're going to
>have to get used to template instantiation.
>
>--
>Fergus Henderson - fjh@munta.cs.mu.oz.au
I don't think that is a good answer. I want to program in C++. In fact, I
do program in C++. I haven't gotten used to template instantiation and I
don't intend on using templates until such time as compiling with them doesn't
take have the day and 3/4 of my machines resources. Templates are a good idea
with a faulty implementation. I haven't had the chance to try out templates
on Sun C++ 4.0 yet. Maybe they've sped things up by now.
Stephen Gevers
sg3235@shelob.sbc.com
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 5 Aug 1994 07:20:37 GMT Raw View
|> You're proposing a language extension to save
|> yourself from having to write one little template class?
I was not thinking only about myself not being the only C++ programmer.
I was not proposing an extension but asking what people think.
|> >I also think that if you use smart pointers you have to use
|> >reference counting; that menas extra space ....
|> No, you don't need to use reference counting.
I had assumed that the term smart pointer was generally understood to
refer to pointers that help with garbage collection (and finding suggestions
about them strange until I saw what you meant).
Is there a standard meaning for the term "smart pointer" ?
|> >Besides template instantiation is a pain.
|> Welcome to C++! If you want to program in C++, you're going to
|> have to get used to template instantiation.
Some time ago someone like you would have said "welcome to C" to people
who did not like the defects of that language. Fortunately Stroustrup was
not of your advice.
|> >Anyway, how can you alway be sure that they are alway inlined? I can't!
|> If your compiler ignores your inline directives, that's a quality of
|> implementation issue. Instead of proposing a language extension to
|> solve the problem, get a better quality implementation.
Should a language be designed taking into account the optimization that the
compilers will do? I do not the answer to this question. I guess this is
a very relevant issue.
|> Fergus Henderson - fjh@munta.cs.mu.oz.au
Enrico.
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Fri, 29 Jul 1994 07:43:20 GMT Raw View
In article <rfgCtLE6p.F54@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>In article <312epq$5gd@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
>>
>>
>>This is an old idea already present (in other form) in other languages (can't remember which).
>>I was wondering about the utility of a keyword/special label at the end of a
>>function such that the code after it is always executed before exiting.
>
>If you have some code that you want to ALWAYS have executed upon exit from
>some scope, you *might* want to take a look at catch clauses. Those
>*might* be suitable. Then again....
Oh POOH!
If you have code you want to always execute before
destroying the outmost local variables of a function and
exiting .. USE A GOTO STATEMENT!
It has EXACTLY the functionality asked for.
void f() {
...
goto endoff;
{
..
goto endoff;
}
endoff:
// endoff code
}
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Wed, 27 Jul 1994 09:25:36 GMT Raw View
In article <312epq$5gd@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
>
>
>This is an old idea already present (in other form) in other languages (can't remember which).
>I was wondering about the utility of a keyword/special label at the end of a
>function such that the code after it is always executed before exiting.
If you have some code that you want to ALWAYS have executed upon exit from
some scope, you *might* want to take a look at catch clauses. Those
*might* be suitable. Then again....
I'm really not sure if there is any way to get a catch clause executed
REGARDLESS of whether you are exiting the relevant scope due to the
propagation of an exception or due to something else (e.g. dropping
out the bottom, a non-local goto, a return, a break, a continue, etc.).
But there *should* be some way of doing this.
I'll ask the other experts gathered here.
Is `catch (...)' able to catch the <null> exception (i.e. the non-exception
exception)? I have no idea. Really. Seems somewhat logical though. After
all, `(...)' generally is understood to mean `may take ZERO or more arguments'.
Then again, maybe a new notation like `catch ()' would be more suitable.
P.S. If you want to know about one way of insuring that something
ALWAYS gets done as you exit a given scope... regardless of the nature
or manner of the exit... well... just define a new class type and give
it a destructor which performs your desired termination actions. Then,
just declare one (dummy) object of this new type in the block where you
want the termination actions to occur. Hey! It's really clumsy, but
I know it works. (Using some flavor of `catch' to do these sorts of
things would be way way cleaner.)
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: olaf@cwi.nl (Olaf Weber)
Date: Wed, 27 Jul 1994 11:50:52 GMT Raw View
In article <rfgCtLE6p.F54@netcom.com>, rfg@netcom.com (Ronald F. Guilmette) writes:
> In article <312epq$5gd@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
>> This is an old idea already present (in other form) in other
>> languages (can't remember which). I was wondering about the
>> utility of a keyword/special label at the end of a function such
>> that the code after it is always executed before exiting.
> If you have some code that you want to ALWAYS have executed upon
> exit from some scope, you *might* want to take a look at catch
> clauses. Those *might* be suitable. Then again....
They're not suitable. This is because catch clauses aren't executed
when a try block is exited normally. In particular, catch (...)
doesn't catch the "non-exception" exception.
So the argument [not quoted by rfg] remains
>> The "resource acquisition as initialization" technique is often too
>> boring for trivial cases like deleting 2,3 pointers and imposes too
>> much overhead.
Yet this idiom does exactly what you want. An "after" clause could
look like this:
void f()
{
Type* p1 = 0;
Type* p2 = 0;
// ...
after:
delete p1;
delete p2;
}
The extra administration to obtain its semantics in C++ looks like
this:
void f()
{
struct fv {
Type1* p1;
Type2* p2;
fv() { p1 = 0; p2 = 0; }
~fv() { delete p1; delete p2; }
} fv;
// ...
}
This is certainly "boring", but "too much overhead" overstates the
case, as a compiler should have no trouble with inlining the
destructor call. This would give maximum performance for normal exit,
and an extra destructor call during stack unwinding, which is also
what can be expected for "after".
Anonymous structures would be nice for this, as you wouldn't need to
qualify the members, or come up with extra names:
// pseudo-code, not valid C++
void f()
{
struct {
Type1* p1;
Type2* p2;
() { p1 = 0; p2 = 0; }
~() { delete p1; delete p2; }
};
// ...
}
The syntax for the constructor and the destructor is atrocious, and
yet the ability to define them for a nameless class is essential to
make this work.
To introduce "after" or anonymous classes just for the convenience of
doing the above just doesn't seem worthwile.
-- Olaf Weber
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 27 Jul 1994 13:22:13 GMT Raw View
In article <CtLKwu.4zK@cwi.nl>, olaf@cwi.nl (Olaf Weber) writes:
|> In article <rfgCtLE6p.F54@netcom.com>, rfg@netcom.com (Ronald F. Guilmette) writes:
|>
|> > In article <312epq$5gd@bull.saltfarm.bt.co.uk> enrico@mround.bt.co.uk (Enrico Viali) writes:
|>
|> >> This is an old idea already present (in other form) in other
|> >> languages (can't remember which). I was wondering about the
|> >> utility of a keyword/special label at the end of a function such
|> >> that the code after it is always executed before exiting.
|> > If you have some code that you want to ALWAYS have executed upon
|> > exit from some scope, you *might* want to take a look at catch
|> > clauses. Those *might* be suitable. Then again....
|> They're not suitable. This is because catch clauses aren't executed
|> when a try block is exited normally. In particular, catch (...)
|> doesn't catch the "non-exception" exception.
I know about catch clauses Etc. but I would not use them for non "exceptional"
cases.
Although I can't be sure I think exceptions slow down the code *if* they are
used as *"normal" statements*.
|> >> The "resource acquisition as initialization" technique is often too
|> >> boring for trivial cases like deleting 2,3 pointers and imposes too
|> >> much overhead.
|> Yet this idiom does exactly what you want. An "after" clause could
|> look like this:
...
|> This is certainly "boring",
|>but "too much overhead" overstates the
|> case, as a compiler should have no trouble with inlining the
|> destructor call. This would give maximum performance for normal exit,
|> and an extra destructor call during stack unwinding, which is also
|> what can be expected for "after".
I agree that I have overstated the case but, based on my (very limited)
experience, I tend not to trust C++ compilers too much.
|> Anonymous structures would be nice for this, as you wouldn't need to
|> qualify the members, or come up with extra names:
|>
|> // pseudo-code, not valid C++
|> void f()
|> {
|> struct {
|> Type1* p1;
|> Type2* p2;
|> () { p1 = 0; p2 = 0; }
|> ~() { delete p1; delete p2; }
|> };
|> // ...
|> }
|>
|> The syntax for the constructor and the destructor is atrocious, and
|> yet the ability to define them for a nameless class is essential to
|> make this work.
I still find nicer (more readable)
void f()
{
Type1 * p1;
Type2 * p2;
after
delete p1;
delete p2;
}
|> To introduce "after" or anonymous classes just for the convenience of
|> doing the above just doesn't seem worthwile.
Probably it is not, but I think that C++ compilers generate some
code that is always executed before exiting a function; so an eventual "after"
clause could be added without too much effort.
Thanks for your comments,
Ciao,
Enrico.
Author: enrico@mround.bt.co.uk (Enrico Viali)
Date: 26 Jul 1994 07:42:50 GMT Raw View
This is an old idea already present (in other form) in other languages (can't remember which).
I was wondering about the utility of a keyword/special label at the end of a
function such that the code after it is always executed before exiting.
(I would disallow "goto"s in the code after such a keyword/special label.)
The "resource acquisition as initialization" technique is often too boring
for trivial cases like deleting 2,3 pointers and imposes too much overhead.
Could some C++ guru comment on (something like) this ?
xxx f(......)
{
// do whatever you want
after
delete p1;
delete p2;
....
}
Thanks,
Enrico