www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opUnary with ++ and -- on a struct that has a dynamic array

reply aliak <something something.com> writes:
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
Feb 11 2018
parent reply rumbu <rumbu rumbu.ro> writes:
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
Feb 11 2018
parent aliak <something something.com> writes:
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
Feb 12 2018