Binding rvalues to ref [WAS: I close BIP27. I won't be pursuing BIPs anymore]

Andrei Alexandrescu via Digitalmars-d digitalmars-d at puremagic.com
Wed Oct 19 04:55:19 PDT 2016


On 10/19/16 1:47 AM, Manu via Digitalmars-d wrote:
> On 19 October 2016 at 06:22, Andrei Alexandrescu via Digitalmars-d
> <digitalmars-d at puremagic.com <mailto:digitalmars-d at puremagic.com>> 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
>
>
> This is obvious though, lval calls the first, rval calls the second.
> Surely most programmers would intuitively expect that behaviour? Is
> there some issue there?

You're missing context. The conversation went like this:

Jonathan: `Andrei said rvalue references were a mistake in C++'

Andrei: `No, I said binding rvalues to const& was a mistake of C++, 
which subsequently led to the necessity of rvalue references.'

Atila: `Indeed, if you cannot distinguish between void fun(ref const 
Foo) and void fun(Foo) then you're going to have a bad time.'

(NOTA BENE: at this point it became unclear whether we discuss C++ or 
hypothetical D code. Atila used D syntax in a discussion about C++'s issue.)

Me: `Affirmative.'

You: `But wait, it's intuitive: lvalues bind to the first, rvalues bind 
to the last.'

Well, I'd agree it's intuitive but C++ won't allow it. These overloads 
are ambiguous in C++ code:

==============
struct S {};
void foo(S);
void foo(const S&); // no error so far (which doesn't help either)

int main() {
     S a;
     foo(a); // ERROR! Ambiguous call!
     const S b;
     foo(b); // ERROR! Ambiguous call!
     foo(S()); // ERROR! Ambiguous call!
     extern const S goo();
     foo(goo()); // ERROR! Ambiguous call!
}
==============

This was C++'s big un' that led to many complications. If the overload 
weren't ambiguous, a large part of rvalue references would have been 
unneeded. (Universal references would still have been necessary for 
perfect forwarding, but that's not the bulk.)

In order to avoid such issues, we steered clear off binding rvalues to 
ref parameters in the D language. As I mentioned to Ethan, I do agree a 
careful definition may be able to avoid the fallout that happened in 
C++. It would be a fair amount of work.


Andrei



More information about the Digitalmars-d mailing list