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