delegate cannot handle polymorphism?

Nub Public nubpublic at gmail.com
Tue Jun 28 07:37:41 PDT 2011


On 6/28/2011 2:54 PM, foobar wrote:
> == Quote from Nub Public (nubpublic at gmail.com)'s article
>> 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?
>
> The above premise is incorrect in that it compares to different concepts. A
> delegate is a closure whereas a c++ member function pointer is not. This means it
> captures the context in which the code was run. In the case of a method call, that
> context would be the specific instance when the delegate was created hence it
> cannot and should not be polymorphic.
>
> Regarding signal/slot designs: see for example C#'s implementation - this is
> incorporated into the language as "events" which are simply arrays of delegates.
> Implementing this via member function pointers is actually the uncommon case since
> most other languages use closures.


Thanks for the clarification.


More information about the Digitalmars-d mailing list