From: reindorf@us-es.sel.de (Charles Reindorf)
Subject: Re: Compiler should generate virtual destructors
Organization: SEL-Alcatel Line Transmission Systems Dept. US/ES
Date: Sat, 23 Jan 93 08:16:16 GMT

In article <lm0gudINN9be@exodus.Eng.Sun.COM>, chased@rbbb.Eng.Sun.COM (David Chase) writes:
|> In article <1993Jan22.081555.12027@us-es.sel.de> reindorf@us-es.sel.de (Charles Reindorf) writes:
|> >On the subject of "trampolenes" in the implementation of nested functions, this 
|> >presumably means the following appraoch:
|> 
|> > [code generation into stack frame, which works.]
|> > ... The main objection I can see is that on some operating systems
|> >you are not allowed to do any run-time code generation.
|> 
|> One workaround is to keep a cache of trampolines, which in this case
|> are pairs of code+data, where each piece of code is compiled to
|> reference a particular piece of data.  Some run-time code generation
|> must still occur.  In the limit case (the least flexible OSes) a
|> different calling convention must be used for all function calls.

As you say, the cache appraoch still involves generating code on the fly, 
or making the function pointer data type more complex (impacting all cases) 
and changing the procedure call convention.
|> 
|> >Other people talk about "bound" functions which presumably means that
|> >given an object a of class A with member function f, then "a.f" can be
|> >regarded as a new function (whose pointer can be taken) with a non
|> >member-function signature.  The only way I can see of using a
|> >trampolene appraoch for this situation is to place the trampolene for
|> >the function a.f into the object a itself.
|> 
|> Actually, you could "new" them.  Just allocate the functions on the
|> "heap", and free them when you are done.  Or, we could take a flying
|> leap at the slippery slope and add garbage collection.

Again, as you say, you have to free them "when you are done", but in 
this situation, there is no natural idea of "when you are done". In 
fact, whereas the natural lifetime of a nested function is until the 
containing function completes, the natural lifetime of a bound function 
is until the destruction of the object to which it is bound. How do you 
ensure that whenever an object dies, that bound function trampolenes 
which *might* have been generated for it are deleted? (Bearing in mind 
that the object may not otherwise need any destructor and may not have 
any virtual functions at all).

|> >This surely makes member function closures an impracticable and
|> >unworkable addition to the language?
|> 
|> I think the answer is another question: "compared to what?"  I'm
|> really looking forward to run-time instantiation of templates.

I can see no way that the solution can be implemented in a way that 
doen't impact the normal performance of the system. The only way I 
can see round this is to add something to the syntax of the language 
to indicate "this member function might be bound" at the point of 
declaration. To me, this is unacceptable.

None of this detracts from the fact that *nested* functions *can* be 
implemented without impacting on the normal performance of the system, 
and without requiring any special new constructs in the language (more 
a relaxation of a rule). What's more, they are extremely valid for 
situations where iterators are used for many general call-back 
mechanisms which are considerably more awkward (or unsafe) when done 
using one of the manual alternatives.

Moreover, if nested functions are implemented, they imply an easy 
manual solution to many cases where bound member functions might have 
been required. Other cases where bound member functions might be 
required can surely be solved through abstract base classes and in some 
cases MI.

|> 
|> David Chase
|> Sun


Newsgroups: comp.std.c++