October 18, 2016
On Tuesday, October 18, 2016 14:07:06 Andrei Alexandrescu via Digitalmars-d wrote:
> On 10/18/2016 01:51 PM, Jonathan M Davis via Digitalmars-d wrote:
> > Andrei has been very vocal about how
> > rvalue references were a horrible mistake in C++
>
> Please misquote appropriately :o). I said binding rvalues to const ref is the mistake that led to the rvalue references complication. That's the truth and nothing but the truth, but not the whole truth; one thing is that the rvalue references features covers additional things not caused by the const ref mistake. -- Andrei

LOL. Sorry, I got the basic idea right but not the specifics. Thanks for the clarification.

- Jonathan M Davis

October 18, 2016
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.

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? 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? If that's the case, I'm not sure that the fact that we don't allow const ref to take rvalues is as big a deal as it would first seem to a C++98 programmer (though it's obviously still somewhat limiting).

- Jonathan M Davis

October 18, 2016
On Tuesday, 18 October 2016 at 17:51:19 UTC, Jonathan M Davis wrote:
> On Tuesday, October 18, 2016 13:36:42 Namespace via Digitalmars-d wrote:
>> On Tuesday, 18 October 2016 at 09:50:35 UTC, ketmar wrote:
>> > On Tuesday, 18 October 2016 at 06:30:15 UTC, Namespace wrote:
>> >> On Tuesday, 18 October 2016 at 02:54:08 UTC, Manu wrote:
>> >>> I just want to be able to pass an rvalue to a function that
>> >>> receives a
>> >>> const ref... that's why I came to this forum in the first
>> >>> place like,
>> >>> 7 years ago. 7 years later... still can't.
>> >>
>> >> I recently wrote a PR for p0nce D idioms, which shows how you
>> >> can do that
>> >> https://github.com/p0nce/d-idioms/pull/119
>> >
>> > there is a huge difference between "i can hack around it" and "i can do it".
>>
>> True. ;) It's like the static-array-without-length-and-gc hack. You can do it with language constructs but it's inconvenient. So it's up to Walter and Andrei to decide if this inconvenience is bearable or not.
>
> Andrei decided ages ago that he didn't think that having const ref take rvalues was a good idea and that he doesn't think that it's a big deal. I don't recall whether Walter has said much on the issue, but AFAIK, he hasn't said anything to contradict that, and Andrei has been very vocal about how rvalue references were a horrible mistake in C++ and that he doesn't want to see anything of the sort in D. auto ref parameters solve the problem on some level, and it seems that that's the closest you're going to get to getting rvalue references in the language. I think that it's pretty clear at this point that it's not very likely that anyone is going to change Andrei's mind on this one.
>
> - Jonathan M Davis

Yep. Therefore my little hack. It works and it isn't such a big inconvenience.
October 18, 2016
On Tuesday, 18 October 2016 at 18:15:18 UTC, ag0aep6g wrote:

> It would be great if we had detailed rationale articles for these non-obvious decisions.

We do, on the wiki:
http://wiki.dlang.org/Language_design_discussions

Feel free to add anything that you think would be of interest to others.
October 18, 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

October 18, 2016
On 10/18/2016 04:15 PM, Atila Neves wrote:
>
> 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".

That's right, thanks Atila. -- Andreu
October 18, 2016
On 18.10.2016 20:15, ag0aep6g wrote:
> On 10/18/2016 07:51 PM, Jonathan M Davis via Digitalmars-d wrote:
>> Andrei decided ages ago that he didn't think that having const ref take
>> rvalues was a good idea and that he doesn't think that it's a big deal. I
>> don't recall whether Walter has said much on the issue, but AFAIK, he
>> hasn't
>> said anything to contradict that, and Andrei has been very vocal about
>> how
>> rvalue references were a horrible mistake in C++ and that he doesn't
>> want to
>> see anything of the sort in D.
>
> It would be great if we had detailed rationale articles for these
> non-obvious decisions.
>
> First, so that people get a nice prepared answer for why D is different.

It wouldn't even be the same thing if it was allowed. D const is not C++ const. Enforcing transitive read-only on rvalue references does not make that much sense.

If rvalues shouldn't be allowed to bind to ref alone, there should just be some additional annotation that allows rvalues to bind to ref, but that additional annotation shouldn't do anything more.
October 18, 2016
On 10/18/2016 11:15 AM, ag0aep6g wrote:
> It would be great if we had detailed rationale articles for these non-obvious
> decisions.

That's what FAQs are for, and if someone wants to collect Andrei's posts on the matter and distill them into a FAQ:

    Why doesn't D do rvalue references?

that would be most helpful. Even if the FAQ entry is not perfect, it will serve as a place to provide clarification, rather than random n.g. bits.

http://dlang.org/faq.html

http://www.prowiki.org/wiki4d/wiki.cgi?FaqRoadmap
October 18, 2016
On 10/18/2016 12:43 PM, bachmeier wrote:
> On Tuesday, 18 October 2016 at 18:15:18 UTC, ag0aep6g wrote:
>
>> It would be great if we had detailed rationale articles for these non-obvious
>> decisions.
>
> We do, on the wiki:
> http://wiki.dlang.org/Language_design_discussions
>
> Feel free to add anything that you think would be of interest to others.


http://wiki.dlang.org/Language_design_discussions#rvalue_references
October 18, 2016
On Tuesday, 18 October 2016 at 20:22:58 UTC, Andrei Alexandrescu wrote:
> On 10/18/2016 04:15 PM, Atila Neves wrote:
>>
>> 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".
>
> That's right, thanks Atila. -- Andreu

Is that really the only reason they aren't being allowed? Whenever I use const& in C++ I generally don't want to copy or move anything. How about adding a new qualifier?

    void func(ruleThemAll(Foo) foo);

    const Foo f;
    func(f);     // ok
    func(Foo()); // ok

// ---

    void func(ref ruleThemAll(Foo) foo);
    void func(ref const Foo);        // error: ruleThemAll can have no overloads that match
                                     // function(Foo) or function(ref Foo)