| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
March 19, 2007 Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
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.
I've attached three test cases (simple Phobos, Phobos, Tango).
EDIT: Someone has explained to me why does this happen, and that I simply cannot do this because that's how things work. Interface Vtable offsets and such - it would have to create a copy to do this (adjust pointers and such). Still, I think it's just too easy to fall for this - and it's hard to figure out a cause for such a bug. The compiler should at least return null for such a typecast - and, in the best case, display a warning or error.
--
Best regards,
Vladimir mailto:thecybershadow@gmail.com
| ||||
March 19, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | 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 | |||
March 19, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote:
> where the literal '8' is used to find the offset of the real vtable of the interface.
Shouldn't that be sizeof(void*)*2 or something similar instead of 8 as pointers isn't the same size on all architectures?
| |||
March 20, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote:
> 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;
Maybe it would be a good idea to add a separate cast expression for reinterpret_cast. The cast(..) can do anything from a C-cast to dynamic_cast to static_cast to reinterpret_cast. All the safe casts can use cast(..) but I think that for conversions without any link between the two types, it would be better to introduce some new cast syntax/keyword.. cast!(..)? :)
L.
| |||
March 20, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | On Tue, 20 Mar 2007 08:29:55 +0200, Lionello Lunesu <lio@lunesu.remove.com> wrote: > Maybe it would be a good idea to add a separate cast expression for reinterpret_cast. The cast(..) can do anything from a C-cast to dynamic_cast to static_cast to reinterpret_cast. All the safe casts can use cast(..) but I think that for conversions without any link between the two types, it would be better to introduce some new cast syntax/keyword.. cast!(..)? :) I agree. Imagine the mess this could accidentally cause in templates. -- Best regards, Vladimir mailto:thecybershadow@gmail.com | |||
March 21, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | Vladimir Panteleev wrote: > On Tue, 20 Mar 2007 08:29:55 +0200, Lionello Lunesu <lio@lunesu.remove.com> wrote: > >> Maybe it would be a good idea to add a separate cast expression for reinterpret_cast. The cast(..) can do anything from a C-cast to dynamic_cast to static_cast to reinterpret_cast. All the safe casts can use cast(..) but I think that for conversions without any link between the two types, it would be better to introduce some new cast syntax/keyword.. cast!(..)? :) > > I agree. Imagine the mess this could accidentally cause in templates. U[] arrcast(U, T)(T[] arr) { U[] result; result.length = arr.length; foreach( i, a ; arr ) result[i] = cast(U)a; return result; } ... I[] i = arrcast!(I)(c); ... We don't need no op-er-a-tor! Hey! You guys! Leave poor cast() alone! All in all it's just a 'nother tem-plated call. :3 -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ | |||
March 26, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote:
>
> Vladimir Panteleev wrote:
>> On Tue, 20 Mar 2007 08:29:55 +0200, Lionello Lunesu <lio@lunesu.remove.com> wrote:
>>
>>> Maybe it would be a good idea to add a separate cast expression for
>>> reinterpret_cast. The cast(..) can do anything from a C-cast to
>>> dynamic_cast to static_cast to reinterpret_cast. All the safe casts can
>>> use cast(..) but I think that for conversions without any link between
>>> the two types, it would be better to introduce some new cast
>>> syntax/keyword.. cast!(..)? :)
>> I agree. Imagine the mess this could accidentally cause in templates.
>
> U[] arrcast(U, T)(T[] arr)
> {
> U[] result;
> result.length = arr.length;
> foreach( i, a ; arr )
> result[i] = cast(U)a;
> return result;
> }
>
> ...
>
> I[] i = arrcast!(I)(c);
Great example. Your arrcast can do anything, from class C:I to I and from class A to class B.
L.
| |||
May 11, 2007 Re: Problem with type-casting to interface arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | On Wed, 21 Mar 2007 02:13:21 +0200, Daniel Keep <daniel.keep.lists@gmail.com> wrote: > Vladimir Panteleev wrote: >> Imagine the mess this could accidentally cause in templates. > > U[] arrcast(U, T)(T[] arr) > { > U[] result; > result.length = arr.length; > foreach( i, a ; arr ) > result[i] = cast(U)a; > return result; > } That's the solution I used in the end. What I meant, however, is: void doTypeCast(T, U)(T from, inout U to) { // perhaps other operations on `from` here to = cast(U)from; // perhaps other operations on `to` here } // with intf. I and class C:I : C[] carr = ....; I[] iarr; // ... doTypeCast(carr, iarr); // this will cause a direct typecast from C[] to I[], which will just completely break things My suggestion was to issue a warning when the user tries to do such broken array typecasts. -- Best regards, Vladimir mailto:thecybershadow@gmail.com | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply