Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
February 22, 2010 When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
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 |
February 23, 2010 Re: When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | > ... > > 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 cast 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! |
February 23, 2010 Re: When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote: >> ... >> >> 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 > > cast is to value conversions what a tactical nuclear strike is to > peaceful negotiations. Yes, that's the C-style casts... > 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, but legal. 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 |
February 23, 2010 Re: When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote:
>> ...
>>
>> 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
>
> cast 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.
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
|
February 24, 2010 Re: When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli Attachments: | Ali Çehreli wrote: > Daniel Keep wrote: >>> ... > <snip> 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 |
February 25, 2010 Re: When is array-to-array cast legal, and what does actually happen? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | 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 |
Copyright © 1999-2021 by the D Language Foundation