"ref const" parameters in functions

L-MAN vangelisforever at yandex.ru
Sat Mar 31 23:39:45 PDT 2012


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(ABC 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   copy of ABC operations:







More information about the Digitalmars-d-learn mailing list