full copies on assignment
1 import std.stdio; 2 3 struct CS{ 4 char[] t; 5 CS opAssign(const CS rhs){ 6 writeln("CS.opAssign called"); 7 this.t = rhs.t.dup; 8 return this;} 9 }; 10 void test_fun(const ref CS rhs){ 11 CS cs = rhs;//error cannot implicitly convert expression (rhs) of type const(CS) to CS 12 CS cs;// these two lines in place of the line above 13 cs = rhs;//now give a program that runs correctly but needs CS.opAssign 14 writeln("cs = ",cs);} 15 16 void main(){ 17 CS rhs; 18 rhs.t="string".dup; 19 test_fun(rhs); 20 return;} In the above program I noticed the impossibility of compiling a declaration of a struct and its assignment in the same line (line 11) inside a function which has, as a parameter, a const ref to the RHS of the assignment. This naively doesn’t seem right because the RHS of an assignment should not be altered by it. On investigating further, I could compile the program (with DMD64 D Compiler v2.071.0) by adding CS.opAssign as indicated and splitting line 11 into lines 12 and 13 as the comments suggest. This has do to with D not making a full (deep) copy on assignment of a CS because it contains a char[], instead giving a pointer to it that could be used to change it. I think full copies should be made on assignment regardless of type. It seems to me that shallow copying of objects is partially in conflict with the const system, and full copying should be the default in assignment (perhaps over-ridable by using a keyword eg alias) which would simplify the const system not giving access to pointers, and would allow the above program to compile in the way I first thought of (without CS.opAssign and lines 12 and 13). I think this is almost the same issue as discussed in “Copying structs with pointers” on 2011-07-20
Re: full copies on assignment
On Tuesday, 24 May 2016 at 15:17:37 UTC, Adam D. Ruppe wrote: On Tuesday, 24 May 2016 at 14:29:53 UTC, John Nixon wrote: This naively doesn’t seem right because the RHS of an assignment should not be altered by it. It's because the char[] being shallow copied still leads to mutable stuff. What I typically do here is just add a method `dup` to the struct that deep copies. Then you do `CS cs = rhs.dup;` when you want to construct it, like you'd do with a copy of a naked array. Thank you for this suggestion, perhaps a slightly neater workaround.
Re: full copies on assignment
On Wednesday, 25 May 2016 at 15:44:34 UTC, Marc Schütz wrote: On Tuesday, 24 May 2016 at 20:58:11 UTC, John Nixon wrote: On Tuesday, 24 May 2016 at 15:17:37 UTC, Adam D. Ruppe wrote: On Tuesday, 24 May 2016 at 14:29:53 UTC, John Nixon wrote: Or add an explicit constructor: struct CS { // ... this(const CS rhs) { this = rhs; } Unfortunately this results in "Error: cannot implicitly convert expression (rhs) of type const(CS) to CS'.
Re: full copies on assignment
On Friday, 27 May 2016 at 08:59:43 UTC, Marc Schütz wrote: Yes indeed it does. Thanks. Something in my version must have been different.
Problem with insertBack
I recently came across another problem with my program in D, found a minimal program showing it, and experimented a little with it as follows: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; void main(){ Array!CS cs_array = make!(Array!CS)(); CS cs; cs.t = "bb".dup; cs_array.insertBack(cs); write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} The first assignment to cs.t[0] changes cs_array as indicated, but the second to cs.t does not. Also if these two assignments are reversed, neither affects cs_array. What could be the explanation of this? Kind regards John Nixon
Re: Problem with insertBack
On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote: On 06/03/2016 04:34 PM, John Nixon wrote: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; Aside: No semicolon after struct declarations in D. void main(){ Array!CS cs_array = make!(Array!CS)(); cs_array stores its data somewhere on the heap. CS cs; cs is on the stack. cs.t = "bb".dup; But cs.t's data is on the heap, like cs_array's. cs.t contains a pointer to it. cs_array.insertBack(cs); This copies cs to cs_array's heap. The pointer in cs.t is being copied, but the data that it points to is not being copied. So cs.t and cs_array[0].t contain two distinct but equal pointers now. Since they're equal, they refer to the same data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! This is expected since cs.t and cs_array[0].t point to the same location. A change to the data through one of them is visible to the other. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not Here you're not writing through the pointer in cs.t, but rather you're assigning a whole new one. Since the pointers in cs.t and cs_array[0].t are independent of each other, they now point to different locations, with different data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote: Thanks very much to you and Steve for the detailed explanation. By the way I did try insertBack(cs.dup) but wasn't sure what I was doing. It seems that I just need to add all the .dup 's when needed to make my program work and find out a procedure to make sure I don't miss any. John Nixon
No line numbers in compiler error messages
I am using dmd v2.067.0 on Mac OSX with Terminal and I found the lack of line numbers surprising. Is there something simple I am doing wrong? Do any of the switches on the command line do this? BTW I only found out about D a couple of weeks back. It seems to be very impressive! John Nixon
Re: No line numbers in compiler error messages
On Friday, 24 April 2015 at 17:45:49 UTC, Steven Schveighoffer wrote: On 4/24/15 1:20 PM, John Nixon wrote: I am using dmd v2.067.0 on Mac OSX with Terminal and I found the lack of line numbers surprising. Is there something simple I am doing wrong? Do any of the switches on the command line do this? It does post line numbers. Please post source and compile line that causes this, and also result so it may be duplicated. -Steve My apologies, the problem was caused by the font colour (black) not visible with Terminal using a black background. John Nixon