On Saturday, 31 March 2012 at 21:42:05 UTC, Jonathan M Davis wrote:
On Saturday, March 31, 2012 23:25:51 L-MAN wrote:
Hello everybody!

I'm trying to use some function FN like this:

struct X
{
  protected double _x;  // double type for example
  public @property double X() const { return _x; }

  // ctor
  public this(double x) { _x = x; } // double type for example

  void FN(ref const(double) in_x) // double type for example
  {
    // ... do some operations with _x
  }

}

main(..)
{
  ....
  X x = X(20);

  x.FN(30); // getting an error
}


  why x.FN(20) gets me an error?
the construction "ref const(double)" or "ref immutable(double)"
must be an rvalue by default I think, but in FN parameter the
compiler expects an lvalue...
  this strategy is the way to some unnecessary copy operations,
when value 20 (or some big struct instead of it) will copy to the
stack..

How can I resolve this problem?

Unlike C++, const ref _must_ be an lvalue just like ref. If you use auto ref instead of const ref, the compiler is supposed to choose between ref and non- ref based on which it thinks would be more efficient, but it currently only
works with templated types.

You can duplicate the function and have a version whose parameter is const ref and one which is not, but be careful if you try and make the non-const ref version call the const ref version (to avoid duplicating the function's body) and make sure that you don't get infinite recursion. It usually works, but I've run into cases before where I ended up with infinite recursion, so make sure
that you have unit tests which check.

Regardless, if you're dealing with a primitive type like double, don't bother with const ref. It's not going to be more efficient. It's with large structs
that you can see a difference.

- Jonathan M Davis

Thank you for reply, but how can I exclude some copy operations?
Look at this sample:

struct ABC // simple class
{
        private double _d=0;
        @property
        {
                double D() const { return _d; }
                double D(double val) { return _d=val; }
        }
        
        this(double d)
        {
                _d = d;
                writeln(" *** ctor ABC, d = ", _d);
        }
        
        ABC opAdd(ABC abc)
        {
                //ABC temp = ABC(this._d+abc._d);
                //return temp;
                return ABC(this._d+abc._d);
        }

        ABC opMul(double d)
        {
                //ABC temp = ABC(this._d*d);
                //return temp;
                return ABC(this._d*d);
        }
                
        ref ABC opAssign(ABC abc)
        {
                this._d = abc.D;
                return this;
        }
        
        ~this()
        {
                writeln(" *** dtor ABC, d = ", _d);
        }
}


struct F {

        private ABC _abc;
        
        @property double D() const { return _abc.D; }
        
        public this(ABC abc)
        {
                _abc = abc;
                
                //abc.D=90;
                //pnt.X = 30;
        }
}


void main(string[] args)
{
  ABC abc1 = ABC(10);
  ABC abc2 = ABC(20);
  F f = F(abc1+abc2*20.0);
  writeln(f.D);
 .......
}

Operation abc1+abc2*20.0 consists of 2 ABC copy:
1. Copy result of abc2*20.0 temp value to opAdd function
2. Copy result of abc1+abc2*20.0 temp2 value to F() ctor
two temp variables and two copy operations.
But if I can use "ref const" rvalue operations 0 copies will be need:
  abc2*20.0 creates temp valiable $$$temp
opAdd(ref const ABC abc) use a ref rvalue to $$$temp, is not a copy
  opAdd return a $$$temp2 that use as ref rvalue for F() ctor
And try to imagine how many unnecessary copies of ABC will create a simple operation like this:
 ((abc1+abc2*20.0)/0.25) + (abc1/abc2)*(abc2-1)....
it killing a time of application, especially if time is critical.

The constructions "auto ref" in return functions values are not working well, if I use it in a "auto ref opAdd(ref const ABC)" "auto ref opMul(double d)" " F.this(ref const ABC)" to exclude some copy operations it gives me a strange result :-((

Thank you!!!


Reply via email to