On Tuesday, 18 October 2016 at 18:33:46 UTC, Jonathan M Davis wrote:
On Tuesday, October 18, 2016 20:15:18 ag0aep6g via Digitalmars-d wrote:
First, so that people get a nice prepared answer for why D is different. I can't confidently spell out why D doesn't allow passing an rvalues in a const ref parameter, and I suspect that only Andrei really can.

He's explained it several times, but I confess that I've never really understood the reasoning. I know C++ well but not at the level of detail that seems to be required to understand what the exact problem is.

I think I get it; I'm just not sure given the comments that pop up in the forum. Isn't one of the main reasons distinguishing between these two?

void fun(ref const Foo);
void fun(Foo);

If they can't be distinguished, you don't get move semantics "for free". With the current rules:

const Foo foo;
fun(foo);   // calls the first one, passes by ref
fun(Foo()); // calls the second one, moves

If rvalues can bind to const, then additional rules for picking one of the overloads have to be introduced. Even if that were done simply, I'm pretty sure a lot of people would believe they were moving when they weren't and vice-versa.

There's a price to pay for the current rules: a possible loss of performance when passing large structs by value, since moving is more expensive than putting a pointer in a register (i.e. pass by ref). I believe this is why Manu wants rvalues to bind to const ref: to not pay that price.

Though as much as folks like passing rvalues to const ref in C++, isn't that generally considered to be bad practice now with C++11/14, because it doesn't play nicely with move constructors?

Not really, no. There are cases where passing by value can generate faster code, but the guideline is still to pass by const T& as before when T is known. In generic code one should pass by T&& and std::forward everything. And, of course, if the performance difference really matters, measure const T& and by-value and go with whichever is fastest. But, by default, const T&.

As mentioned above, moving is better than copying, but doing nothing at is usually better than moving.

 Or at least, there are many cases where you would
have used const ref previously that now you shouldn't, because it forces a copy for lvalues in some cases, whereas just passing by value would allow a move to be made?

Sometimes even the move is elided, similarly to RVO and NRVO.


Reply via email to