Jump to page: 1 2
Thread overview
Find struct not passed by reference
Aug 02, 2021
frame
Aug 02, 2021
jfondren
Aug 03, 2021
frame
Aug 03, 2021
frame
Aug 03, 2021
Paul Backus
Aug 03, 2021
frame
Aug 03, 2021
Tejas
Aug 03, 2021
frame
Aug 03, 2021
Ali Çehreli
Aug 03, 2021
frame
Aug 03, 2021
jfondren
Aug 03, 2021
frame
Aug 03, 2021
Ali Çehreli
August 02, 2021

Is there a way to find a struct which should be passed by reference but accidentally isn't? Maybe with copy constructors?

August 02, 2021

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:

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:

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;
}
August 03, 2021

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.

August 03, 2021

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:

Unique!myType rs = query();

which body is:

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?

August 03, 2021

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:

Unique!myType rs = query();

which body is:

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:

Unique!myType* rs = &query();
August 03, 2021

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:

Unique!myType* rs = &query();

Thanks. I feared that. So something like

ref T var = ...

does not exist (yet)?

August 03, 2021

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:

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:

void main()
{
    ref int i;
}



error: variable `onlineapp.main.i` only parameters or `foreach` declarations can be `ref`
August 03, 2021

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:

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.

August 03, 2021
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
August 03, 2021
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?



« First   ‹ Prev
1 2