April 02, 2002
"Russell Borogove" <kaleja@estarcion.com> wrote in message news:3CA9E738.30607@estarcion.com...

> 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?

No. Delegate variable stores both pointer to object and to method,
and it doesn't care about object's class at all. When you call
the pointer, it passes the object to the function as if it was
"this". As the result, pointers to member functions behave in
the same way as pointers to static functions - you won't see
any difference. It would be even better if, like in C#, delegates
would be able to hold pointers to static functions as well
(when pointer to object == null), and be able to call both types
properly.


April 02, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a8ct2q$2ain$1@digitaldaemon.com...

> Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a
hard
> pointer.

There's no reason in storing index to vtbl, since you have a pointer to _object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.



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 :(

So, an object should be able to change type during it's lifetime?  That's not an operation that's supported in any OO-language that I know of - absent ugly unsupported pointer-poking hacks.  It wasn't too many message ago I was reading how Walter was messing with the vtbl in his platform/compiler-specific code - for shame, Walter!  :-)

Even so, it supportable by having a method pointer be {object pointer, vtbl offset}, rather than {function pointer, object pointer}.  Not really a big deal when all methods are virtual; problematic when many are not (as in C++).

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)



April 02, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a8ctft$2ao5$1@digitaldaemon.com...
> "Walter" <walter@digitalmars.com> wrote in message news:a8ct2q$2ain$1@digitaldaemon.com...
> > Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a
> hard
> > pointer.
> There's no reason in storing index to vtbl, since you have a pointer to _object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.

Is it expected to work with non-member functions too, with member functions arbitrarilly mixed in?


April 02, 2002
"Richard Krehbiel" <rich@kastle.com> wrote in message news:a8d3jm$2ejp$1@digitaldaemon.com...

> ugly unsupported pointer-poking hacks.  It wasn't too many message ago I
was
> reading how Walter was messing with the vtbl in his platform/compiler-specific code - for shame, Walter!  :-)

Well, actually, it was me messing with the vtbl =)

> Even so, it supportable by having a method pointer be {object pointer,
vtbl
> offset}, rather than {function pointer, object pointer}.  Not really a big deal when all methods are virtual; problematic when many are not (as in

Don't see any reason in it; why store the offset, if the value there is constant and doesn't change as program runs? Isn't it simplier AND faster to store the pointer itself, especially since not all methods are virtual (compiler decides).


April 02, 2002
Richard Krehbiel wrote:

> So, an object should be able to change type during it's lifetime?  That's not an operation that's supported in any OO-language that I know of - absent ugly unsupported pointer-poking hacks.  It wasn't too many message ago I was reading how Walter was messing with the vtbl in his platform/compiler-specific code - for shame, Walter!  :-)

Guess I wasn't clear.  :)  I meant this only for member function pointers that did NOT include the object pointer.  That is, you attach the pointer at one time and at a later date use it against some object(s).  The pointer, in this case, would use the appropriate virtual function for the object it was run against.

However, if we only support pointers to static members and pointers to members WITH the object pointer, then you're right, this point is moot.

--
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
Walter wrote:

> "Pavel Minayev" <evilone@omen.ru> wrote in message news:a8ctft$2ao5$1@digitaldaemon.com...
> > "Walter" <walter@digitalmars.com> wrote in message news:a8ct2q$2ain$1@digitaldaemon.com...
> > > Hmm. I wonder if the "pointer to function" part is a vtbl[] index or a
> > hard
> > > pointer.
> > There's no reason in storing index to vtbl, since you have a pointer to _object_, not _class_ - and object's class (and thus all vtbl entries) is known at run-time. So, when you write &foo, the compiler looks for this function in the vtbl, gets the pointer, and stores it into the delegate struct.
>
> Is it expected to work with non-member functions too, with member functions arbitrarilly mixed in?

It would be nice to have a type that could mix pointer-to-member-function-with-object and pointer-to-global-function, but this might be too much to ask for from the compiler.

--
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
"Richard Krehbiel" <rich@kastle.com> wrote in message news:a8d3jm$2ejp$1@digitaldaemon.com...
> So, an object should be able to change type during it's lifetime?  That's not an operation that's supported in any OO-language that I know of -
absent
> ugly unsupported pointer-poking hacks.  It wasn't too many message ago I
was
> reading how Walter was messing with the vtbl in his platform/compiler-specific code - for shame, Walter!  :-)


All's fair when trying to win benchmarks!


April 02, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a8d3t1$2em9$1@digitaldaemon.com...

> Is it expected to work with non-member functions too, with member
functions
> arbitrarilly mixed in?

It would be just great (and it is the way C# delegates work). Practically, internals could look like this:

    // format of delegate pointer
    struct Delegate
    {
        Object obj;
        void* func;
    }



    class Form { void bar(int n); }
    Form foo;
    void baz(int n);
    delegate void ptr(int);    // declare delegate pointer

    ptr = &foo.bar;    // store pointer to method bar() of object foo
/*
Implemented as:
    ptr.obj = foo;
    ptr.func = &foo.classinfo.vtbl[bar];
*/

    ptr(666);    // call it
/*
Implemented as:
    if (obj != null)   // member function (our case)
        (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666);
    else       // static function
        (cast(void (*ptr)(int)) ptr.func)(666);
*/

    ptr = &baz;    // store pointer to function baz()
/*
Implemented as:
    ptr.obj = null;
    ptr.func = &baz;
*/

    ptr(666);    // call it
/*
Implemented as:
    if (obj != null)   // member function
        (cast(void (*ptr)(Object, int)) ptr.func)(obj, 666);
    else       // static function (our case)
        (cast(void (*ptr)(int)) ptr.func)(666);
*/


As you can see, the check is done at run-time. This makes things a bit
slower,
but more flexible. For example, you could write:


    // sorts array of strings, using user-defined comparison function
    void sort(char[][] s, delegate int cmp(char[], char[]));


    int my_sort(char[] s1, char[] s2);
    sort(foo, &my_sort);


    class Bar
    {
        bit case_sensitive;

        int bar_sort(char[] s1, char[] s2)
        {
            if (this.case_sensitive)
                ...
            else
                ...
        }

        void baz()
        {
            sort(foo, &bar_sort);
        }
    }



April 02, 2002
Here's some C++ code snippets to demonstrate how delegates/events work in C#.  Note that C# borrows heavily for Java: there are no global functions, everything is in some class.



   Dan



class DelegatesAndEvents

{

            // C#: public delegate void PrintString(string s);

            typedef DelegateT<Object::void1_T<string>::mf_t, string> PrintString_;

public:

            template <typename OBJECT>

                        static PrintString_ PrintString(OBJECT& o, void (OBJECT::*mf)(string)) {

                        return PrintString_(o, static_cast<Object::void1_T<string>::mf_t>(mf));

            }

            // C#: public event PrintString MyPrintString;

            PrintString_::Event MyPrintString;



            void FirePrintString(string s) {

                        MyPrintString(s);

            }

};



class MyDelegates : public ObjectT<MyDelegates>

{

private:

            string m_name;

public:

            void SimpleDelegateFunction(string s)

            {

                        printf("SimpleDelegateFunction called from %s, string=%s\n", m_name, s);

            }

};



void main()

{

DelegatesAndEvents dae;

            MyDelegates d;



            dae.MyPrintString += DelegatesAndEvents::PrintString(d, &MyDelegates::SimpleDelegateFunction);



            dae.FirePrintString("Event fired!");

}