ref struct member function

Ali Çehreli acehreli at yahoo.com
Thu May 13 19:48:44 UTC 2021


On 5/13/21 12:40 PM, Steven Schveighoffer wrote:
> On 5/13/21 3:21 PM, PinDPlugga wrote:
> 
>> This works but issues a deprecation warning:
>> ```
>> onlineapp.d(30): Deprecation: returning `this` escapes a reference to 
>> parameter `this`
>> onlineapp.d(30):        perhaps annotate the parameter with `return`
>> Fraction(1, 3)
>> ```
>>
>> I found several other ways to make this work without the warnings, but 
>> I am wondering how to make this particular case work, or if it is not 
>> a recommended way, what the proper way would be.
> 
> Just follow the recommendation:
> 
> ```d
> ref Fraction reduce() return { // annotated with return
> ```
> 
> This means, "I will return all or part of the parameter passed in" (the 
> parameter being the `this` reference)
> 
> -Steve

I was writing this example that shows a use case for the problem (marked 
with BUG below):

struct Fraction {
     auto n = 0L;
     auto d = 1L;

     // ... other bits ...

     ref Fraction reduce() {
       import std.numeric : gcd;

       // v = gcd(n, d);
       // if (v > 1) {
       //   n /= v;
       //   d /= v;
       // }

       return this;
     }

     // ... etc ...
}

ref foo() {
   import std.stdio : writeln;
   auto f = Fraction(3, 9);

   // BUG: Returns reference to an object on the stack
   return f.reduce();
}

void main() {
   // Refers to a temporary (it would be a copy without the &)
   auto f = &foo();

   // Do some unrelated things hoping that space for dead objects on
   // the stack will be reused.
   import std.stdio;
   import std.random;
   writeln("doing something else: ", uniform(0, 6));

   writeln(f.d); // Access dead and overwritten object (does NOT print
                 // 9 on my system)
}

Putting 'return' where Steve shows makes the compiler guard us against 
this misuse and the program thankfully does not compile.

Ali



More information about the Digitalmars-d-learn mailing list