April 02, 2002
Isn't it the same as pointers to static member functions (I might be getting something wrong)?

Russ Lewis wrote:
>     * 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.

April 02, 2002
So, "event" consists of both an object pointer and a virtual function? Is the event an array of these, called sequentially, or only the "top of stack" last entry is called?

"Pavel Minayev" <evilone@omen.ru> wrote in message news:a8afmg$sb6$1@digitaldaemon.com...
> "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 02, 2002
Russ Lewis wrote:
> 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.

I'm not sure I understand -- normally, wouldn't the target-object
pointer be part of the call, rather than part of the function
pointer?

-Russell B

April 02, 2002
Jan Jezabek wrote:

> Isn't it the same as pointers to static member functions (I might be
> getting something wrong)?
>
> Russ Lewis wrote:
> >     * 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'm thinking more along the lines of things that might be registered for a class of objects, but when called should be called as member objects, not static.  This would work when you have a group of related objects, and you want to save a single function pointer that is the handler for a particular event for ALL of those objects.

Also, I think that member function pointers should properly handle virtual calls. That is, you can save a pointer to a virtual function (remember, all member functions in D are virtual automatically), and the code will, at runtime, call the right virtual version of it.  This probably would require the compiler to create wrapper functions in some circumstances :(

--
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
Russell Borogove wrote:

> I'm not sure I understand -- normally, wouldn't the target-object pointer be part of the call, rather than part of the function pointer?

Let's use Pavel's example.  We have created a button object, which has some standard behavior.  Then we create a form that includes that button.  When the button is pressed, we want a specific function in the form to be called.  Thus, we have a function pointer in the Button object, which we set to point at the form object.  When the button is pressed, this function is called.

Now, it makes no sense in this example to have a "generic" function pointer that can be called on any object...we only want the call to go to one specific Form object.  Thus, if you don't include the pointer to the Form in the function pointer, then you have to have a 2nd variable in the Button that stores the pointer to the Form.

Worse, you have to remember that this Button is a standard object which could be included in many things...Forms, dialogs, message boxes, etc.  So we can't actually store a pointer to type Form there...instead, we have to store a pointer to Object, since it could point to any type of object.  But will the function pointer syntax allow you to call a member function pointer to Form when all you have is a pointer to an Object?

Anyhow, what I'm saying is that in some circumstances, it doesn't make any sense to separate the function pointer from the object it is intended to be called with.

--
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
Russ Lewis wrote:
> I'm thinking more along the lines of things that might be registered for a class of
> objects, but when called should be called as member objects, not static.  This
> would work when you have a group of related objects, and you want to save a single
> function pointer that is the handler for a particular event for ALL of those
> objects.

Something like a static pointer to a non-static member function? :) I think it's already there in C++. I have no experience in C# so I don't know if there are static delegates.

> Also, I think that member function pointers should properly handle virtual calls.
> That is, you can save a pointer to a virtual function (remember, all member
> functions in D are virtual automatically), and the code will, at runtime, call the
> right virtual version of it.  This probably would require the compiler to create
> wrapper functions in some circumstances :(

I think it is easier than having mixed virtual and non-virtual functions. Consider the following example:

#include <stdio.h>

class base
{
  public:
    int a()
    {
      printf("base\n");
    }
    virtual int b()
    {
      printf("base\n");
    }
};

class derived: public base
{
  public:
    int a()
    {
      printf("derived\n");
    }
    virtual int b()
    {
      printf("derived\n");
    }
};

int main()
{
  int (base::*ptr)();

  base X;
  derived Y;

  ptr = &base::a; // non-virtual

  (X.*ptr)(); // prints "base"
  (Y.*ptr)(); // prints "base"

  ptr = &base::b; // virtual

  (X.*ptr)(); // prints "base"
  (Y.*ptr)(); // prints "derived"

  return 0;
}

How does the code know whether to call a virtual or a non-virtual function?

April 02, 2002
In C# (actually, the .NET framework), an object pointer and a pointer to one of its member functions are wrapped up into a single object called a "Delegate", the C# "delegate" keyword makes it easy to create a Delegate object.  An Event object is a collection of delegates; the collection itself is a "set" because 1) a calling order is not defined and 2) adding the same delegate twice does not result in two calls.

   Dan

"Walter" <walter@digitalmars.com> wrote in message news:a8corb$28g2$1@digitaldaemon.com...
> So, "event" consists of both an object pointer and a virtual function? Is the event an array of these, called sequentially, or only the "top of
stack"
> last entry is called?
>
> "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8afmg$sb6$1@digitaldaemon.com...
> > "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 02, 2002
Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a hard pointer.

"J. Daniel Smith" <j_daniel_smith@HoTMaiL.com> wrote in message news:a8cr62$29g9$1@digitaldaemon.com...
> In C# (actually, the .NET framework), an object pointer and a pointer to
one
> of its member functions are wrapped up into a single object called a "Delegate", the C# "delegate" keyword makes it easy to create a Delegate object.  An Event object is a collection of delegates; the collection
itself
> is a "set" because 1) a calling order is not defined and 2) adding the
same
> delegate twice does not result in two calls.
>
>    Dan
>
> "Walter" <walter@digitalmars.com> wrote in message news:a8corb$28g2$1@digitaldaemon.com...
> > So, "event" consists of both an object pointer and a virtual function?
Is
> > the event an array of these, called sequentially, or only the "top of
> stack"
> > last entry is called?
> >
> > "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8afmg$sb6$1@digitaldaemon.com...
> > > "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 02, 2002
"Jan Jezabek" <jezabek@poczta.onet.pl> wrote in message news:3CA9E3ED.3060600@poczta.onet.pl...

> Isn't it the same as pointers to static member functions (I might be
> getting something wrong)?

It is the same type of pointers you could see in C++:

    class Foo;
    void (Foo::*ptr)();    // pointer to member of Foo

    Foo foo;
    foo->*ptr();    // call it

I don't really see much need in it, however. In my experience (not so long, but still...), I've never ever used C++ pointers to members. Can anyone give a sample where these might be useful?



April 02, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3CA9E742.B2C0766E@deming-os.org...

> Also, I think that member function pointers should properly handle virtual
calls.
> That is, you can save a pointer to a virtual function (remember, all
member
> functions in D are virtual automatically), and the code will, at runtime,
call the
> right virtual version of it.  This probably would require the compiler to
create
> wrapper functions in some circumstances :(

You probably mean for the second type of pointers (to class members rather
than to object members)?

Once again, I don't think these are of real importance, for now at least.
Delegates are, on one hand, more useful, and on other, seem to be simpler
to implement (so we can hope to convince Walter to do it relatively
easy =)).