How to make a generic function to take a class or struct by reference?

Ali Çehreli acehreli at yahoo.com
Mon Mar 28 21:56:55 UTC 2022


On 3/27/22 09:27, JN wrote:
 > I would like to have only one definition of getX if possible, because
 > they both are doing the same thing. I can't remove the ref one, because
 > without a ref it will pass the struct as a temporary and compiler won't
 > like that.

Combining all responses, the code at the bottom is a working example.

First, we should remove the by-value getX function but then class 
function fails expectedly:

class Bar
{
     int x;

     void doStuff()
     {
       *getX(this) = 5;  // <-- Compilation ERROR
     }
}

It may be worth going over why it fails to compile: 'this' happens to be 
of type Bar. Since classes are reference types, the 'this' is of type 
Bar (a reference) but it is an rvalue. (It is an rvalue because there is 
no one variable 'this' for this or any object.) rvalues cannot be passed 
by-reference; so the compilation fails.

So, assuming the by-value getX() is removed, the following would make 
the code compile:

class Bar
{
     int x;

     void doStuff()
     {
       auto this_ = this;
       *getX(this_) = 5;  // <-- Now compiles
     }
}

In that case we pass 'this_', which is clearly an lvalue and it can be 
passed by-reference. (lvalue becaues it is a variable sitting on the stack.)

But we don't want to do the above everywhere, so 'auto ref' is a 
solution. The reason is, it would copy the rvalue (the object reference) 
arguments and it wouldn't be an error because the copied rvalue would be 
another reference to the same class object and it would work.

import std.stdio;

struct Foo
{
     int x;

     void doStuff()
     {
       *getX(this) = 5;
     }
}

class Bar
{
     int x;

     void doStuff()
     {
       *getX(this) = 5;
     }
}

auto getX(T)(auto ref T t)
{
   return &t.x;
}

void main()
{
     Foo foo;
     Bar bar = new Bar();

     foo.doStuff();
     bar.doStuff();

     assert(foo.x == 5);
     assert(bar.x == 5);
}

Ali



More information about the Digitalmars-d-learn mailing list