I close BIP27. I won't be pursuing BIPs anymore

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Tue Oct 18 13:15:00 PDT 2016


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.

Atila



More information about the Digitalmars-d mailing list