April 01, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a8a89q$hd7$1@digitaldaemon.com...
> "J. Daniel Smith" <j_daniel_smith@HoTMaiL.com> wrote in message news:a89tgs$bmi$1@digitaldaemon.com...
> > This looks a lot like C#'s "delegates and events" mechanism.
Coincidence?
> > Is it worth making this technique a standard part of the language like
C#?
> I proposed it a hundred times already!
> Probably, I wasn't that convincing... =)

The problem is I don't understand the problem. I've been buried with work lately, and haven't given that issue the attention it needs. -Walter


April 01, 2002
Essentially, C#'s delegates are a way to easily maintain a collection of (member-) function pointers; firing an event invokes each of the function pointers.  With a bit of work, you can achieve similar functionality in C++, although you need templates (and ideally partial template specialization) for type-safety.  Building the feature directly into the language makes the syntax a lot easier (and neither C# or D have templates making it harder to "roll your own").

   Dan

"Walter" <walter@digitalmars.com> wrote in message news:a8ad5n$r5c$1@digitaldaemon.com...
>
> "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8a89q$hd7$1@digitaldaemon.com...
> > "J. Daniel Smith" <j_daniel_smith@HoTMaiL.com> wrote in message news:a89tgs$bmi$1@digitaldaemon.com...
> > > This looks a lot like C#'s "delegates and events" mechanism.
> Coincidence?
> > > Is it worth making this technique a standard part of the language like
> C#?
> > I proposed it a hundred times already!
> > Probably, I wasn't that convincing... =)
>
> The problem is I don't understand the problem. I've been buried with work lately, and haven't given that issue the attention it needs. -Walter
>
>


April 01, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a8ad5n$r5c$1@digitaldaemon.com...

> The problem is I don't understand the problem. I've been buried with work lately, and haven't given that issue the attention it needs. -Walter

First of all, an example:

    class Button
    {
        event void onMouseMove(int, int);    // event (pointer to function)
        ...
        void mouseMoved(int x, int y)
        {
            // raise event (will first call OK_MouseMove1, then
OK_MouseMove2)
            onMouseMove(x, y);
        }
    }

    void OK_MouseMove1(int x, int y)    // global event handler
    {
        ...
    }

    class MyForm: Form
    {
        Button OK;

        void OK_MouseMove2(int x, int y)    // local event handler
        {
            ...
        }

        this()
        {
            OK.onMouseMove = OK_MouseMove1;    // set event handler
            OK.onMouseMove ~= OK_MouseMove2;   // add another handler
        }

    }

Advantage of this approach is that you can make global, static, and
nonstatic
member functions event handlers - unlike usual function pointers, which
only allow global and static functions. In most cases, event handler is
actually part of the class, and now, to make it work, it needs to be
declared static, and to get "this" pointer as one of explicit arguments:

    static void OK_MouseMove(Object self, int x, int y)
    {
        ...
    }

Not only this requires typing "self.blablabla" all the time (or wrap the function into with-block), but you also have to cast self to whatever class it actually is...


April 01, 2002
Also, note that several handlers may be attached to a single event slot. Practically, it's an array of pointers, not a single pointer, and functions are called in straight order:

    event void onInit();
    void foo();
    void bar();
    void baz();

    onInit = &foo;             // set
    onInit = &onInit ~ &bar;   // add another
    onInit ~= &baz;            // one more
    onInit = onInit[0 .. 1] ~  // remove bar()
        onInit[2 .. 3];

    onInit();    // call foo(), then baz()




April 01, 2002
> > Oh, God, Walter, it's too bad you can't make the D language specification require reasonable indentation!   ;)
> Well, he could just make pointers to methods... =)
I completely agree with Pavel that we Must make pointers to methods I think it'll be more convinient to develop software using it.... I ask You about it. Not only for me, but for whole Dcommunity....


April 01, 2002
Svyatoslav Bezgin wrote:

> I ask You about it. Not only for me, but for whole Dcommunity....

Maybe, since we're moving from C to D, we should be known as a dommunity...  :)

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


April 02, 2002
I think that pointers to member functions (which as far as I know aren't there in D) should be explicitly castable to a normal function pointer, for example:

  class one
  {
    public:
      int x(int y);
  };

  typedef int (*FPTR)(void *, int);

  void main()
  {
    FPTR z = (FPTR) &one::x; // this will give an error
    one instance;

    z(&instance, 10); // same as instance->x
  }

If such cast was legal, it would solve your problem (of course I might be wrong:). Of course it's quite inconvenient, and I would prefer using delegates just as I preferred virtual functions over function pointers.

> Advantage of this approach is that you can make global, static, and
> nonstatic
> member functions event handlers - unlike usual function pointers, which
> only allow global and static functions. In most cases, event handler is
> actually part of the class, and now, to make it work, it needs to be
> declared static, and to get "this" pointer as one of explicit arguments:
> 
>     static void OK_MouseMove(Object self, int x, int y)
>     {
>         ...
>     }
> 
> Not only this requires typing "self.blablabla" all the time (or wrap the
> function into with-block), but you also have to cast self to whatever
> class it actually is...


April 02, 2002
"Jan Jezabek" <jezabek@poczta.onet.pl> wrote in message news:3CA9DC00.4070601@poczta.onet.pl...

> I think that pointers to member functions (which as far as I know aren't there in D) should be explicitly castable to a normal function pointer, for example:
>
>    class one
>    {
>      public:
>        int x(int y);
>    };
>
>    typedef int (*FPTR)(void *, int);
>
>    void main()
>    {
>      FPTR z = (FPTR) &one::x; // this will give an error
>      one instance;
>
>      z(&instance, 10); // same as instance->x
>    }

Don't forget that there is no fixed calling convention in D, functions might get called in a way different from methods, so this is not guaranteed to work...


April 02, 2002
Pavel Minayev wrote:

> "Jan Jezabek" <jezabek@poczta.onet.pl> wrote in message news:3CA9DC00.4070601@poczta.onet.pl...
>
> Don't forget that there is no fixed calling convention in D, functions might get called in a way different from methods, so this is not guaranteed to work...

Function pointers need to specify the calling conventions, then...including, perhaps a "D-member-function" calling convention.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


April 02, 2002
There are two key types of member function pointers; if D supports member function pointers, it should support both:

    * Pointers that include a pointer to the object they are to be called on.
These are useful for event handlers and such, where you know which object
should handle the event.
    * Pointers that do NOT include an object pointer.  These are useful where
you might have a class (perhaps a child class) register the handler to use on
ANY of its objects when a certain event occurs.

I don't know what a good syntax for the two types might be.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]