www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Find struct not passed by reference

reply frame <frame86 live.com> writes:
Is there a way to find a struct which should be passed by 
reference but accidentally isn't? Maybe with copy constructors?
Aug 02 2021
next sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Monday, 2 August 2021 at 23:06:42 UTC, frame wrote:
 Is there a way to find a struct which should be passed by 
 reference but accidentally isn't? Maybe with copy constructors?
disable postblit: ```d struct NoCopy { int n; disable this(this); } void modify(NoCopy nc) { nc.n++; } void main() { NoCopy x; x.modify; // Error: struct `catchcopy.NoCopy` is not copyable ... } ``` std.typecons.Unique: ```d import std.typecons : Unique; class Val { int n; } void incr(Unique!Val v) { v.n++; } void decr(ref Unique!Val v) { v.n--; } void show(Unique!Val v) { import std.stdio : writeln; writeln(v.n); } void main() { Unique!Val x = new Val; // x.incr; // Error: ... is not copyable x.decr; x.release.show; } ```
Aug 02 2021
parent reply frame <frame86 live.com> writes:
On Monday, 2 August 2021 at 23:19:48 UTC, jfondren wrote:
 On Monday, 2 August 2021 at 23:06:42 UTC, frame wrote:
 Is there a way to find a struct which should be passed by 
 reference but accidentally isn't? Maybe with copy constructors?
disable postblit:
Well, I have to change a struct to be passed by reference now and don't want to manually inspect where the compiler complains - which is nearly everwhere. The compiler would also not distinguish between a reference assignment.
 std.typecons.Unique:
This could work, thanks for the hint.
Aug 03 2021
parent reply frame <frame86 live.com> writes:
On Tuesday, 3 August 2021 at 10:25:34 UTC, frame wrote:

 This could work, thanks for the hint.
I was too optimistic. I get the error: ``` struct `std.typecons.Unique!(myType).Unique` is not copyable because it is annotated with ` disable` ``` on a line like: ```d Unique!myType rs = query(); ``` which body is: ```d ref Unique!myType query(A...)(A args) { return queryImpl(args); // also ref to ref, back to creation of the struct } ``` It's not an Unique! problem, I also get the error if I just disable the postblit. Removing the ref from queryImpl! prints the error at query(), so it really sees the error just at the line above but why?
Aug 03 2021
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 3 August 2021 at 11:31:02 UTC, frame wrote:
 On Tuesday, 3 August 2021 at 10:25:34 UTC, frame wrote:

 This could work, thanks for the hint.
I was too optimistic. I get the error: ``` struct `std.typecons.Unique!(myType).Unique` is not copyable because it is annotated with ` disable` ``` on a line like: ```d Unique!myType rs = query(); ``` which body is: ```d ref Unique!myType query(A...)(A args) { return queryImpl(args); // also ref to ref, back to creation of the struct } ``` It's not an Unique! problem, I also get the error if I just disable the postblit. Removing the ref from queryImpl! prints the error at query(), so it really sees the error just at the line above but why?
You can't assign a `ref` to a variable; if you try, a copy is created. What you can do instead is use a pointer: ```d Unique!myType* rs = &query(); ```
Aug 03 2021
parent reply frame <frame86 live.com> writes:
On Tuesday, 3 August 2021 at 11:55:51 UTC, Paul Backus wrote:

 You can't assign a `ref` to a variable; if you try, a copy is 
 created.

 What you can do instead is use a pointer:

 ```d
 Unique!myType* rs = &query();
 ```
Thanks. I feared that. So something like ``` ref T var = ... ``` does not exist (yet)?
Aug 03 2021
parent reply Tejas <notrealemail gmail.com> writes:
On Tuesday, 3 August 2021 at 12:23:38 UTC, frame wrote:
 On Tuesday, 3 August 2021 at 11:55:51 UTC, Paul Backus wrote:

 You can't assign a `ref` to a variable; if you try, a copy is 
 created.

 What you can do instead is use a pointer:

 ```d
 Unique!myType* rs = &query();
 ```
Thanks. I feared that. So something like ``` ref T var = ... ``` does not exist (yet)?
No. ```ref``` can only be used as a function/template. or ```foreach``` parameter. eg: ```d void main() { ref int i; } error: variable `onlineapp.main.i` only parameters or `foreach` declarations can be `ref` ```
Aug 03 2021
parent frame <frame86 live.com> writes:
On Tuesday, 3 August 2021 at 13:23:04 UTC, Tejas wrote:

 No. ```ref``` can only be used as a function/template. or 
 ```foreach``` parameter.
Yeah, I know. I was in hope of a DIP or something. I just would like to hijack the reference chain to do something like: ```d void fun() { ref T rs; scope(failure) { rs.close(); } rs = query(); otherFunc(rs); } ``` I removed the ref and changed my code to use pointers instead.
Aug 03 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/2/21 4:06 PM, frame wrote:
 Is there a way to find a struct which should be passed by reference but 
 accidentally isn't? Maybe with copy constructors?
If I understand it correctly, your current value-type needs to be a reference type. Would the following be workable solutions? a) Classes are already reference types. So, replace struct with class: class Foo { // ... } b) Make your struct a reference type by i) Renaming it struct FooImplementation { // ... } ii) Using a wrapper with the old name struct Foo { FooImplementation * impl; this(int i) { this.impl = new FooImplementation(i); } // ... } But the problem with the 'b' option is, all objects are being allocated dynamically with that constructor. Then, there can be a ref-taking constructor (as well): struct Foo { // ... this(ref FooImplementation impl) { this.impl = &impl; } } Finally, an 'alias this' can make the transition easy in the 'b' case. Ali
Aug 03 2021
parent reply frame <frame86 live.com> writes:
On Tuesday, 3 August 2021 at 16:35:04 UTC, Ali Çehreli wrote:

 a) Classes are already reference types. So, replace struct with 
 class:

 class Foo {
   // ...
 }
It's already a member of an object, so I don't like it to make it a sub object.
 b) Make your struct a reference type by

 i) Renaming it
Was thinking of something similar but end with the raw pointer solution. I just made an alias on it and had just to remove the ref-keywords from the methods. The only thing that bothers me is that I cannot use it via foreach() without an opApply() layer between. Why foreach() does not accept a pointer?
Aug 03 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Tuesday, 3 August 2021 at 19:11:16 UTC, frame wrote:
 On Tuesday, 3 August 2021 at 16:35:04 UTC, Ali Çehreli wrote:
 Why foreach() does not accept a pointer?
pointers don't come with a length?
Aug 03 2021
parent reply frame <frame86 live.com> writes:
On Tuesday, 3 August 2021 at 19:19:27 UTC, jfondren wrote:
 On Tuesday, 3 August 2021 at 19:11:16 UTC, frame wrote:
 On Tuesday, 3 August 2021 at 16:35:04 UTC, Ali Çehreli wrote:
 Why foreach() does not accept a pointer?
pointers don't come with a length?
Where is the problem if it points to something with a range interface?
Aug 03 2021
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/3/21 12:22 PM, frame wrote:
 On Tuesday, 3 August 2021 at 19:19:27 UTC, jfondren wrote:
 On Tuesday, 3 August 2021 at 19:11:16 UTC, frame wrote:
 On Tuesday, 3 August 2021 at 16:35:04 UTC, Ali =C3=87ehreli wrote:
 Why foreach() does not accept a pointer?
pointers don't come with a length?
=20 Where is the problem if it points to something with a range interface?
Must be more complicated than a trivial derefencing: import std.range; void main() { auto r =3D 5.iota; auto p =3D &r; foreach (e; *p) { } } Having said that, I swear there is a seemingly-over-the-top help of D=20 for foreach loops, which I can't remember now. Similar to what you said, = it works with a certain type of construct by thinking outside the box. Do others know what I am trying to remember? Ali
Aug 03 2021