Problem with type-casting to interface arrays

Derek Parnell derek at nomail.afraid.org
Sun Mar 18 23:41:10 PDT 2007


On Mon, 19 Mar 2007 07:52:15 +0200, Vladimir Panteleev wrote:

> Hi,
> 
> With an interface I and an implementation C : I, is this code sane?
> 
>      C[] c = [new C()];
>      I[] i = cast(I[]) c;
> 
> Currently, any attempts to do this typecast fail for me (the objects
> inside i are corrupted/unusable).
> I don't see why it should fail (per the spec), so I'm inclined to
> believe it's a compiler bug.

The thing is that "cast(I)" and "cast(I[])" do different things.

The code ...
   I[] i = cast(I[]) c;

literally makes i.ptr the same as c.ptr. And so it effectively means that
'i' is now an array of classes and not an array interfaces.

Consider this ...

   float[] f = [4.23, 1.2345];
   int[] i = cast(int[])f;

This does not cause each float in 'f' to be converted to 'int' but instead
just makes 'i' point to the floats in 'f'. This is important in your case
because the RAM structure of an interface is not the same as a class. So
even though you code "writefln(i[0].classinfo.name);" in your example, the
code is actually referencing a class layout and not an interface layout.

To do what you hoped, you'd have to this horrible kludge ...

  writefln((cast(I)(8+(cast(void*)i[0]))).classinfo.name); 

where the literal '8' is used to find the offset of the real vtable of the
interface.

You could of course build the interface array at run time ...

   C[] c = [new C()];
   I[] i;
   foreach(C k; c) i &= cast(I)k;

The "cast(I)" actually causes the compiler to convert the class to an
interface just like "cast(int)4.213" causes it to convert the float to an
int.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
19/03/2007 5:30:44 PM



More information about the Digitalmars-d mailing list