Understanding lvalue and rvalue

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Apr 27 22:21:26 PDT 2017


On 04/28/2017 06:46 AM, ANtlord wrote:
> struct MyStruct
> {
>     @disable this(this);
>     int a;
> }
>
> void process(MyStruct obj) {
>     writeln("incoming rvalue");
> }
>
> void process(in ref MyStruct obj) {
>     writeln("incoming lvalue");
> }
>
> void main()
> {
>     MyStruct obj = {a: 1};
>     process(obj);
> }
>
> Text of the error is "struct app.MyStruct is not copyable because it is
> annotated with @disable"

Regarding overloads, the spec [1] defines an "exact match" to win over a 
"match with conversion to const". On `ref` it only says that "literals 
[i.e. rvalues] do not match `ref` [...] parameters".

In your code, the non-ref variant is an exact match for `obj`. Be aware 
that the non-ref overload accepts lvalues as well as rvalues.

The ref-variant is not considered an exact match, because calling it 
involves converting `obj` to `const MyStruct`.

So, that's why the non-ref version wins in your code. Everything works 
as specified here.

> Also I try to change word `in` by `const` and I get same result. But
> when I remove `in` program is compiled.

When you remove `in`, the ref overload becomes an exact match as well. 
Now the compiler has to choose between two exact matches. The spec says 
that "partial ordering" is then used to find the correct overload. I'm 
not sure if the text properly describes how that works for ref vs 
non-ref, though. In practice, the compiler prefers a ref overload over a 
non-ref overload, *if* they have the same match level.

Instead of removing `in`/`const` from the ref overload, you can also add 
it to the non-ref overload. Again, the overloads will have the same 
match level ("match with conversion to const"), and the ref version will 
win.



[1] https://dlang.org/spec/function.html#function-overloading


More information about the Digitalmars-d-learn mailing list