object - interface compatibility

BCS BCS at pathlink.com
Tue Nov 14 10:55:56 PST 2006


Frank Benoit (keinfarbton) wrote:
> Yes, thanks for you example.
> 
> To make my question more clear:
> 
> 1.) Is this reference manipulation really absolutely necessary? Why?
> 2.) Isn't there a way to make class and iface really compatible?
 > 3.) Please document this very cleanly in the D spec.
 >
 > Frank

In short, No. The long version is that while it could be done, it would 
add a lot of overhead to everything and only fix a problem that is run 
into occasionally.

Actually I ran into this difference a while back, what it amounts to (if 
I understand it correctly) is that the calling convention for interfaces 
is different than that for objects.

For object it amounts to some variation on this (in sudo ASM)

//obj.test(a, b, c);

push c
push b
push a	// push args

mov obj -> r1	// load pointer to object

mov *r1 -> r2	// load v-tbl

push r1		// push "this"

call r2[test]	// use v-tbl to call test




for an interface this is about what is done


//inf.test(a, b, c);

push c
push b
push a	// push args

mov obj -> r1	// load pointer to object

mov *r1 -> r2	// load v-tbl

		// adjust interface to point to object
		// uses information from interface v-tbl
add r1 r2[__offset] -> r1

push r1		// push "this"

call *(r2+test)	// use v-tbl to call test


the interface calling convention adds one more memory fetch and an add. 
Not a lot but it does add to the overhead and complexity that D's single 
inheritance model is trying to avoid.


Actually I would like to see interface calling convention changed to use 
a fat pointer for interfaces. This would use a arbitrary context pointer 
welded to a pointer to a v-tbl. All sorts of cool things could be done 
with this.

interface literals working like delegate literals
3rd party interface implementation for classes*
interfaces from structs, arrays and any arbitrary pointers.

In effect any reference can be used as a context and as the basis for an 
interface


<D version >= 2.0 feature suggestion>

(*)

something like this

// third party closed source code
class Foo
{
	int baz();
	char bar();
	void go(int i);
}


// your code
interface I
{
	void Go();
	void Stop();
}


weld Baz : [Foo:I]
{
	void Go()
	{
		this.go(1);
	}
	void Stop()
	{
		this.go(0);
	}
}


void func(I);

void main()
{
	auto f = new Foo;
	func(f);	// fails (Foo cant be converted to I)
	func(Baz(f));	// works
}

Baz is of type I, when a Foo is converted to a Baz all that needs to 
happen is join the Foo pointer and Baz's v-tbl pointer.



More information about the Digitalmars-d mailing list