delegate cannot handle polymorphism?

Nub Public nubpublic at gmail.com
Mon Jun 27 19:23:32 PDT 2011


On 6/28/2011 1:29 AM, Timon Gehr wrote:
> Nub Public wrote:
>> On 6/27/2011 7:08 PM, Michel Fortin wrote:
>>> On 2011-06-27 03:30:09 -0400, Nub Public<nubpublic at gmail.com>  said:
>>>
>>>> class BOn 6/27/2011 7:08 PM, Michel Fortin wrote:
>>> On 2011-06-27 03:30:09 -0400, Nub Public<nubpublic at gmail.com>  said:
>>>
>>>> class B
>>>> {
>>>> void fun() { writeln("B"); }
>>>> }
>>>>
>>>> class D : B
>>>> {
>>>> override void fun() { writeln("D"); }
>>>> }
>>>>
>>>> void delegate() dg =&b.fun;
>>>> dg.ptr = cast(void*)d;
>>>> dg();
>>>>
>>>>
>>>> Compiler: DMD 2.053
>>>> It prints "B" instead of "D".
>>>> The equivalent code in C++ prints "D" nicely.
>>>
>>> C++ doesn't have delegates, and D doesn't have member function pointers.
>>> Resolving virtual functions is done while you take its address in D,
>>> while in C++ the member function pointer type contains holds the vtable
>>> offset (or several in the case of multiple inheritance) which gets
>>> resolved only when you call the function.
>>>
>>> If you want the C++ behaviour, try using a delegate literal as a
>>> trampoline that gets the object as a parameter to then call your function:
>>>
>>> void delegate(B b) dg = (B b) { b.fun(); };
>>>
>>> dg(d);
>>>
>>
>>
>> Thank you. That was very helpful.
>>
>> What's the rational for this behavior though? Resolving the address of a
>> virtual function at compile time seems a little counter-intuitive to me.
>> I guess this way is slightly more efficient.
>
> A delegate literal consists of a function pointer and a context pointer. There is
> no polymorphism in that. A member function is a normal function you can take the
> address of.


I see.

> In general, you shouldn't update one of (ptr,funcptr) without updating the other
> unless you have good reasons to do so and know exactly what you are doing.
> Not having member pointers is AFAIK a direct consequence of the fact that nobody
> uses them in C++ and almost nobody even knows that they exist.
> Furthermore, their implementation is too involved, given their limited usefulness.
>
> Cheers,
> -Timon


I have to disagree on this.
Member function pointers are useful in many event handling systems. 
Imagine a signal and slot system. To register a member function as a 
slot, the most direct and intuitive way is to take a member function 
pointer. In c++0x and boost, <function>, <functional> and related 
libraries all work with member function pointers.

My premise is simple: a virtual function should always be resolved by 
the dynamic identity of the object, regardless of whether it is called 
directly or through a function pointer.

Perhaps the contextptr of D delegate cannot do this because it can refer 
to the enclosing context besides an object. But I'd love it for D to 
have the functionality of a truly polymorhic member function pointer. 
Maybe the restrictions on the keyword "function" can be relaxed to work 
with such a pointer?


More information about the Digitalmars-d mailing list