From 5033751810682980707
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,4453ceff0a5ed7f7
X-Google-Attributes: gidf78e5,public
From: Don Griffin <dgriffin@no.spam.farallon.com>
Subject: Re: Closures again :) (long)
Date: 1997/09/02
Message-ID: <340C4620.8340BE04@no.spam.farallon.com>#1/1
X-Deja-AN: 269606678
References: <34046A78.DD58DA46@no.spam.farallon.com> <3405AB62.1C08@vega.co.uk>
X-Original-Date: Tue, 02 Sep 1997 12:00:16 -0500
X-Priority: 3 (Normal)
Originator: austern@isolde.mti.sgi.com
Organization: Farallon Computing Inc.
X-Auth: PGPMoose V1.1 PGP comp.std.c++ iQBVAwUBNAyB4ky4NqrwXLNJAQFzVwH+J5kr3lXWEiTum/6xLhhGjMSEcaqTGJW6 hp3MamajjfGw38Xcx19fVMWtbZnpqJZJLv3I3zaNenLzJPmcmmfZCw== =jCLz
Newsgroups: comp.std.c++


Richard,

Thanks for taking the time to reply.  Bob Steagall pointed me to an
alternate implementation (by Rich Hickey) that is much better than what
I posted.  It removes the virtual method from TFunctorX and provides
pass-by-value semantics for the closures (which is what I really
wanted).

> How about specifying the interface you would want to be able to use the
> closures?  Then it would be possible to see how close we can get
> currently, and how much overhead the compiler would be able to remove.
>

My ideal syntax would be:

    Declare a closure type:

        typedef void (class::*PEvent) (int);

    Create a closure:

        class TFoo {
        public:
            void OnEvent (int);
        };

        PEvent ev = closure <this, OnEvent>;

    The type of "this" is used to determine which class OnEvent comes
from.  And
    from inside a non-static TFoo method, the "this" parameter can be
implicit
    in the closure:

        ev = closure <OnEvent>;

What I have come up with provides this syntax:

    Declare a closure type:

        typedef TFunctor1<void,int>  PEvent;

    Create a closure:

        PEvent ev = closure (this, &TFoo::OnEvent);

I decided not to use a macro for the implicit "this" form of closure,
nor could I remove "&TFoo::" to take the address of the method.  As it
turns out, to pull off this clean syntax, I need partial template
specialization to handle "void" returns.  Or, I could use "closure" for
non-void returns and "closure_v" or something for void returns.

> It seems to me that most of the price is inevitable, and getting the
> compiler to implement the workings instead of a library writer wouldn't
> make it go away.  Neither do I find it too cumbersome.
> 

The size of a TFunctor1<void,int> using VC++5 is 20 bytes.  I imagine
that most other compilers would have 16, since VC5 uses 16-bytes for
method pointers and most other compilers use only 12.

I think that the compiler could create 8-byte closures with almost no
overhead beyond that of a normal function pointer.  The price for this? 
Move the cost of determining the addresses to the creation of the
closure.

Using traditional method pointers, the compiler does not know the class
of the object on which the pointer will be used, and hence must store
extra information to make the call properly.  However, with a closure,
the compiler has object and method in hand and could resolve them to the
proper value for "this" and the true 4-byte address for the method to
call.  This tradeoff is probably well worth it, because an event driven
system based on closures will make many more calls through closures than
creations of closures.  Certainly, the compiler has helper functions
already in place to do this kind of thing, so this optimization doesn't
sound too difficult.

Using templates I can get most of what I want, but the perfectionist in
me would very much like to see closures (and properties, but that's
another discussion<g>) in the language.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your 
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]



