Thread overview
opUnary with ++ and -- on a struct that has a dynamic array
Feb 12, 2018
aliak
Feb 12, 2018
rumbu
Feb 12, 2018
aliak
February 12, 2018
Hi,

Is there a way to get post increment and pre increment working properly in this scenario?

import std.stdio;

struct A {
    int[] a;
    this(int a) { this.a = [a]; }
    auto opUnary(string op)(){
        return A(mixin(op ~ "this.a[0]"));
    }
}

void main() {
    auto a = A(0);
    int b = 0;
    writeln(a++, ":", b++); // 1, 0 <-- wrong post increment result
    writeln(++a, ":", ++b); // 2, 2
}

If I switch the order of the mixin expression (i.e. "this.a[0]" ~ op) then the pre increment does not work.

Any tips?

Cheers
- Ali
February 12, 2018
On Monday, 12 February 2018 at 03:13:43 UTC, aliak wrote:
> Hi,
>
> Is there a way to get post increment and pre increment working properly in this scenario?
>
> import std.stdio;
>
> struct A {
>     int[] a;
>     this(int a) { this.a = [a]; }
>     auto opUnary(string op)(){
>         return A(mixin(op ~ "this.a[0]"));
>     }
> }
>
> void main() {
>     auto a = A(0);
>     int b = 0;
>     writeln(a++, ":", b++); // 1, 0 <-- wrong post increment result
>     writeln(++a, ":", ++b); // 2, 2
> }

writeln(a++) translates to:

A copy = a;
a.opUnary!"++";
writeln(copy);

copy.a[] and a.a[] are the same reference, you increment a.a[0]/copy.a[0] in opUnary

to make this work you will need a postblit constructor:

struct A
{
   ....
   this(this)
   {
     a = a.dup; //make a copy a;
   }
}

In fact, you'll find exactly the same scenario in docs: https://dlang.org/spec/struct.html#struct-postblit

>
> If I switch the order of the mixin expression (i.e. "this.a[0]" ~ op) then the pre increment does not work.
>
> Any tips?
>
> Cheers
> - Ali


February 12, 2018
On Monday, 12 February 2018 at 06:16:21 UTC, rumbu wrote:
> writeln(a++) translates to:
>
> A copy = a;
> a.opUnary!"++";
> writeln(copy);
>
> copy.a[] and a.a[] are the same reference, you increment a.a[0]/copy.a[0] in opUnary
>
> to make this work you will need a postblit constructor:
>
> struct A
> {
>    ....
>    this(this)
>    {
>      a = a.dup; //make a copy a;
>    }
> }
>
> In fact, you'll find exactly the same scenario in docs: https://dlang.org/spec/struct.html#struct-postblit
>

Ah! Awesome. Yes that works, thank you!

Cheers