"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