digitalmars.D - Problem with type-casting to interface arrays
- Vladimir Panteleev (19/19) Mar 18 2007 Hi,
- Derek Parnell (31/42) Mar 18 2007 The thing is that "cast(I)" and "cast(I[])" do different things.
- Johan Granberg (3/5) Mar 19 2007 Shouldn't that be sizeof(void*)*2 or something similar instead of 8 as
- Lionello Lunesu (8/26) Mar 19 2007 Maybe it would be a good idea to add a separate cast expression for
- Vladimir Panteleev (5/11) Mar 20 2007 I agree. Imagine the mess this could accidentally cause in templates.
- Daniel Keep (26/36) Mar 20 2007 U[] arrcast(U, T)(T[] arr)
- Lionello Lunesu (4/28) Mar 26 2007 Great example. Your arrcast can do anything, from class C:I to I and
- Vladimir Panteleev (20/30) May 11 2007 That's the solution I used in the end. What I meant, however, is:
Hi, With an interface I and an implementation C : I, is this code sane? C[] c =3D [new C()]; I[] i =3D cast(I[]) c; Currently, any attempts to do this typecast fail for me (the objects ins= ide i are corrupted/unusable). I don't see why it should fail (per the spec), so I'm inclined to believ= e 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 simpl= y cannot do this because that's how things work. Interface Vtable offset= s 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 warn= ing or error. -- = Best regards, Vladimir mailto:thecybershadow gmail.com
Mar 18 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
Mar 18 2007
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?
Mar 19 2007
Derek Parnell wrote:On Mon, 19 Mar 2007 07:52:15 +0200, Vladimir Panteleev 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!(..)? :) L.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;
Mar 19 2007
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
Mar 20 2007
Vladimir Panteleev wrote:On Tue, 20 Mar 2007 08:29:55 +0200, Lionello Lunesu <lio lunesu.remove.com> wrote: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/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.
Mar 20 2007
Daniel Keep wrote:Vladimir Panteleev wrote:Great example. Your arrcast can do anything, from class C:I to I and from class A to class B. L.On Tue, 20 Mar 2007 08:29:55 +0200, Lionello Lunesu <lio lunesu.remove.com> wrote: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);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.
Mar 26 2007
On Wed, 21 Mar 2007 02:13:21 +0200, Daniel Keep <daniel.keep.lists gmail= .com> wrote:Vladimir Panteleev wrote: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 =3D cast(U)from; // perhaps other operations on `to` here } // with intf. I and class C:I : C[] carr =3D ....; I[] iarr; // ... doTypeCast(carr, iarr); // this will cause a direct typecast from C[] t= o I[], which will just completely break things My suggestion was to issue a warning when the user tries to do such brok= en array typecasts. -- = Best regards, Vladimir mailto:thecybershadow gmail.comImagine the mess this could accidentally cause in templates.U[] arrcast(U, T)(T[] arr) { U[] result; result.length =3D arr.length; foreach( i, a ; arr ) result[i] =3D cast(U)a; return result; }
May 11 2007