www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Understanding lvalue and rvalue

reply ANtlord <antlord92 gmail.com> writes:
Hello! Short time ago I've met strange thing at least for me. I 
have a non-copyable structure and two methods for it with same 
name. I mean that I use function overloading.

First method takes rvalue of this structure. Second method takes 
constant lvalue structure. But when I try to use this function 
with instantiated object I get compile error.

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"

Also I try to change word `in` by `const` and I get same result. 
But when I remove `in` program is compiled. Is this mug or 
feature. If feature, please help to understand it. Should I pass 
structure instances by pointer? Like

void process(in MyStruct* obj) {
	writeln("incoming lvalue");
}

void main()
{
	MyStruct obj = {a: 1};
	process(&obj);
}

Does make sense for me because it is more obvious in client code, 
but I want to understand reason of error pointed above.

Thanks. Sorry if my English is not clear.
Apr 27 2017
next sibling parent ANtlord <antlord92 gmail.com> writes:
On Friday, 28 April 2017 at 04:46:00 UTC, ANtlord wrote:
 Does make sense for me because it is more obvious in client 
 code, but I want to understand reason of error pointed above.
Typo fix. It makes sense for me*
Apr 27 2017
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
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
Apr 27 2017
parent ANtlord <antlord92 gmail.com> writes:
On Friday, 28 April 2017 at 05:21:26 UTC, ag0aep6g wrote:
 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.
It works. I don't know why I've decided to make rvalue parameter non-const. It makes sense. It's clear answer. Thank you very much!
Apr 28 2017