digitalmars.D.learn - When is array-to-array cast legal, and what does actually happen?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (33/33) Feb 22 2010 Is the following cast legal with dmd 2.040?
- Daniel Keep (21/30) Feb 22 2010 cast is to value conversions what a tactical nuclear strike is to
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (13/45) Feb 22 2010 As you point out in the footnote, cast are not always pointer
- div0 (20/23) Feb 23 2010 -----BEGIN PGP SIGNED MESSAGE-----
- Lars T. Kyllingstad (15/45) Feb 23 2010 There is another gotcha to watch out for: Array literals are treated
- bearophile (5/10) Feb 24 2010 From your idea I have written some comments here:
Is the following cast legal with dmd 2.040? struct MyChar { dchar d; this(dchar param) in { assert(false); // not called } body { d = param; assert(d != param); // not called } this(this) in { assert(false); // not called } body { assert(d != d); // not called } } void main() { MyChar[] mine = cast(MyChar[])("hello"d); // legal? assert(mine[0].d == 'h'); } I see that neither the constructor nor the postblit is called. Apparently the bit representation is used. This has the risk of violating struct invariants. Is it legal? Thank you, Ali
Feb 22 2010
... I see that neither the constructor nor the postblit is called. Apparently the bit representation is used. This has the risk of violating struct invariants. Is it legal? Thank you, Alicast is to value conversions what a tactical nuclear strike is to peaceful negotiations. cast is specifically *designed* to circumvent the type system's protections [1]. If you want to do a value conversion, *do a value conversion*. Allocate a new array and convert each member. cast doesn't call the constructor or the postblit because it's doing a pointer conversion. Your code is basically equivalent to this: void main() { auto tmp = "hello"d; auto mine = cast(MyChar*)(tmp.ptr) [0..(tmp.length*typeof(tmp[0]).sizeof)/MyChar.sizeof)]; } That is, it's doing an unsafe, unchecked pointer cast, then re-slicing the array. To answer your question: yes, it's legal. Not what you wanted, but legal. [1] Except for int<->float. Oh, and objects. Really, this is one thing I could just about strangle K&R for: conflating value-preserving, non-value-preserving *AND* unsafe conversions all into a single construct. Walter, gets slapped with a fish for not putting a bullet in cast's head when he had the chance. Argh!
Feb 22 2010
Daniel Keep wrote:Yes, that's the C-style casts...... I see that neither the constructor nor the postblit is called. Apparently the bit representation is used. This has the risk of violating struct invariants. Is it legal? Thank you, Alicast is to value conversions what a tactical nuclear strike is to peaceful negotiations.cast is specifically *designed* to circumvent the type system's protections [1]. If you want to do a value conversion, *do a value conversion*. Allocate a new array and convert each member. cast doesn't call the constructor or the postblit because it's doing a pointer conversion.As you point out in the footnote, cast are not always pointer conversions. :) I am wondering whether the compiler could call the constructors for each array element in array-to-array conversion.Your code is basically equivalent to this: void main() { auto tmp = "hello"d; auto mine = cast(MyChar*)(tmp.ptr) [0..(tmp.length*typeof(tmp[0]).sizeof)/MyChar.sizeof)]; } That is, it's doing an unsafe, unchecked pointer cast, then re-slicing the array.Especially when there is the method above, it feels more like array casting could call the constructors.To answer your question: yes, it's legal. Not what you wanted, butlegal. Actually it will work for me, but I will leave it for later when optimizing the code. And there are no invariants in my case; any dchar will do.[1] Except for int<->float. Oh, and objects. Really, this is one thing I could just about strangle K&R for: conflating value-preserving, non-value-preserving *AND* unsafe conversions all into a single construct. Walter, gets slapped with a fish for not putting a bullet in cast's head when he had the chance. Argh!Ali
Feb 22 2010
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Ali Çehreli wrote:Daniel Keep wrote:Well I forget the details, but it's been pointed out before that D's cast is fundamentally broken. You get one cast operator that hides the full set of c++ static, dynamic, const & reinterpret casts. Which one actually happens is a mystery. Not ideal by any means and really should be addressed before D2 is called final. Not going to happen though. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFLhHH6T9LetA9XoXwRAjavAJ9LV2XmRQ67GdC7qv03E9DMyaFPVACgp+JZ w4qYBuMc++WUWJPkc1ZR93c= =F1Qb -----END PGP SIGNATURE-----<snip>...
Feb 23 2010
Daniel Keep wrote:There is another gotcha to watch out for: Array literals are treated differently from other arrays. That is, the compiler does a value conversion for literals. import std.stdio; void main() { auto a = [1, 2, 3]; auto b = cast(float[]) a; auto c = cast(float[]) [1, 2, 3]; writeln(a); // Prints "1 2 3" writeln(b); // Prints "1.4013e-45 2.8026e-45 4.2039e-45" writeln(c); // Prints "1 2 3" } -Lars... I see that neither the constructor nor the postblit is called. Apparently the bit representation is used. This has the risk of violating struct invariants. Is it legal? Thank you, Alicast is to value conversions what a tactical nuclear strike is to peaceful negotiations. cast is specifically *designed* to circumvent the type system's protections [1]. If you want to do a value conversion, *do a value conversion*. Allocate a new array and convert each member. cast doesn't call the constructor or the postblit because it's doing a pointer conversion. Your code is basically equivalent to this: void main() { auto tmp = "hello"d; auto mine = cast(MyChar*)(tmp.ptr) [0..(tmp.length*typeof(tmp[0]).sizeof)/MyChar.sizeof)]; } That is, it's doing an unsafe, unchecked pointer cast, then re-slicing the array.
Feb 23 2010
Daniel Keep:[1] Except for int<->float. Oh, and objects. Really, this is one thing I could just about strangle K&R for: conflating value-preserving, non-value-preserving *AND* unsafe conversions all into a single construct. Walter, gets slapped with a fish for not putting a bullet in cast's head when he had the chance. Argh!From your idea I have written some comments here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=106750 Bye, bearophile
Feb 24 2010