February 08, 2010
On Mon, 08 Feb 2010 17:19:28 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Steven Schveighoffer wrote:
>> On Mon, 08 Feb 2010 16:09:19 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> Steven Schveighoffer wrote:
>>>> On Mon, 08 Feb 2010 15:13:33 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>>
>>>>> Steven Schveighoffer wrote:
>>>>>> On Mon, 08 Feb 2010 14:36:37 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>>>>
>>>>>>> Don wrote:
>>>>>>>>  I don't understand this. How does belowTop() know how to call top()?
>>>>>>>
>>>>>>> It calls top() through the normal interface mechanism. Inside belowTop(), this has Stack!T type.
>>>>>>  Actually, I think Don has a point here.  A virtual function (even on an interface) is always called with the 'this' pointer, not the interface pointer.
>>>>>
>>>>> That is done via an adjustment of the reference. In the case of an interface method, no adjustment is necessary. Inside the method, "this" has the static type of the interface and the dynamic type whichever class implements the interface.
>>>>   void foo(Stack!T st)
>>>> {
>>>>   auto x = st.belowTop();
>>>> }
>>>>  OK, so if st's virtual function for belowTop points to the default implementation, there is no adjustment.  But what if the actual object *did* override the default implementation?  Does it also receive the interface pointer as 'this'?  Where does the adjustment happen?  What happens if you have a reference to the actual concrete object type?  Do you have to thunk to the correct interface to pass in the expected interface pointer?  It can't be both ways.
>>>
>>> If an object overrode the default implementation, the pointer to method belowTop will point to code that does do the adjustment.
>>  If I understand this correctly, calling such a "default implementation" function is different than calling a standard interface function.  And each entry in such an interface for a overridden method will point to a "pre function" that adjusts the 'this' reference before jumping to the real implementation.
>
> Actually that's what's happening today.

Yes, but I think it's happening at the call site and not inside the function itself.

I will run a test...

You are right, I was wrong.  So this is already the way it works (good to know!):


interface I
{
    void foo();
}

interface J
{
    void foo();
}

class C : I, J
{
    int i;
    void foo() { i = 5;}
}

produces the following asm for C.foo:

_D13testinterface1C3fooMFZv:
		push	EBP
		mov	EBP,ESP
		sub	ESP,4
		mov	dword ptr 8[EAX],5
		leave
		ret
		nop
_TMP0:
		add	EAX,0FFFFFFF4h
		jmp	near ptr _D13testinterface1C3fooMFZv
_TMP1:
		add	EAX,0FFFFFFF0h
		jmp	near ptr _D13testinterface1C3fooMFZv

where _TMP0 and _TMP1 are the little pre functions that get stored in the interface vtables.

I therefore don't think there are any issues, I misunderstood the way interface functions work.  I didn't realize the interface function called a little pre function.  I thought it was done at the call site before the call.

>
>> The vtable entries of the object itself would point to a function that does not do the adjustment, correct?
>
> Yes, but let's not forget that each object stores more than one vptrs.

Right, I just thought the different vtables contained identical references to the same functions.  It makes sense that is not the case.

>> I think all the information is available to make this work, the only issue I see is that a function with a default implementation artificially changes the ABI for that function.  Adding a default implementation therefore will make compiled objects incompatible, even with the same vtable layout.
>
> Not getting this, but I'll let Walter weigh in.

It's my bad, I thought normal interface calls were different than this method of having a little "pre" function, but it makes sense to do it that way.

Sorry for the noise.  I retract my objection on these grounds :)

-Steve
1 2 3 4
Next ›   Last »