Binding rvalues to const ref in D

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Wed Oct 19 08:18:36 PDT 2016


New post since the the last one was already off-topic. Continued 
from:

http://forum.dlang.org/post/nu7mv8$mqu$1@digitalmars.com

I get the feeling that people are talking past each other. I'm 
going to give my view of the situation and everybody can correct 
me if I'm wrong / throw tomatoes at me.code

On the one hand some people want rvalues to bind to const ref. I 
can only assume that they want this because they want to pass 
rvalues to a function efficiently - i.e. put a pointer in a 
register. It might also be due to familiarity with C++ but I 
speculate. If indeed I'm right, then I wonder if it's by instinct 
or if it's been measured versus passing a struct by value. I just 
wrote this:

struct Vector { float x, y, z; }
float silly(Vector v) { return v.x * 5; }

float test() {
     Vector v;
     return silly(Vector(1, 2, 3)) * 7;
}

Yes, it's a stupid example. But ldc2 -O3 gives me this for 
`silly`:

movq   rax,xmm0
movd   xmm0,eax
mulss  xmm0,DWORD PTR [rip+0x0]
ret

It's a bit longer than if I passed in a float directly:

mulss  xmm0,DWORD PTR [rip+0x0]
ret

But... there's no copying or moving of the entire struct. C++ 
(also passing by value, I just hand-tranlated the code) is 
similar but for some reason was better at optimising:

mulss  xmm0,DWORD PTR [rip+0x0]
ret
nop

Again, no copying or moving. Which is what I expected. Granted, 
real-life code might be complicated enough to make matters a lot 
worse. I'm just wondering out loud how likely that is to happen 
and how big of an impact on total performance that'll have. My 
question is: do you _really_ need rvalues to bind to const ref 
for performance? If not, what _do_ you need it for? Is it an 
instinctive reaction against passing structs by value from C++98 
days?

It's been mentioned that one might not get a say on how a 
function is declared if calling, say, C++ from D. That's a fair 
argument, and one I've not heard a solution for yet. Maybe allow 
rvalues to bind to const ref in `extern(C++)`? I don't know, I'm 
thinking out "loud".


On the other hand we have the "rvalues binding to const ref => 
rvalue references or other complicated mechanisms for figuring 
out whether or not the const ref is an rvalue". This seems to 
have not been explained correctly. I'm not blaming anyone, I just 
tried yesterday and failed as well.

The situation is this: if one wants move semantics, one must know 
when one can move. Because rvalues bind to const& in C++, you 
never know whether the const& is an lvalue or rvalue. The 
solution to this was rvalue references, which are refs that can 
_only_ bind to rvalues. That way you know that the origin was an 
rvalue an wahey, move semantics. They complicated the language 
significantly. Did you know there's more than one kind of rvalue 
in C++? Oh yes:

http://en.cppreference.com/w/cpp/language/value_category

Do we want that? I don't.

Summary:

* rvalues don't bind to const ref because if they did there'd be 
ambiguity, and to solving that problem would make the language 
more complicated.
* Knowing when passed-in parameters were actually rvalues turns 
out to be something compilers want to do because performance.
* It'd be nice if D could call C++ functions that take const& 
with rvalues

Tomato time?

Atila






More information about the Digitalmars-d mailing list