On Fri, 01 Mar 2013 19:49:54 -0500, Era Scarecrow <rtcv...@yahoo.com>
wrote:
On Friday, 1 March 2013 at 23:46:36 UTC, Steven Schveighoffer wrote:
This is the major problem that Andrei had with it (at least as I
understand his past statements) -- it conflates const with rvalue
references. Sometimes, you want a const ref that does NOT bind to an
rvalue.
If I have a medium sized struct that I only intend to read/reference
from I see no reason not to use 'const ref' for simplicity and speed
(and avoid postblit hopefully) but when it's an Rvalue I need to make a
second function either duplicate except signature or forwarding the
value.
The point is simple:
foo(ref M m)
foo(M m)
An lvalue, yes, we want that to bind to ref.
But an rvalue? I want that to bind to foo(M m), otherwise I would not
have added that method. The by-value version is *more efficient* than the
by-ref version with rvalues, even for large structs.
But what if I ALSO want to say that foo doesn't change m? Well, that's
easy! I just do:
foo(const ref M m)
But this makes rvalues bind to that version too! This is the problem. I
want it to be ref, to avoid copies of a larg struct, and I want it to be
const, for contract purposes, I DIDN'T want it to accept rvalues.
The point is, there is a legitimate reason to mark a parameter const ref
BESIDES wanting to have it bind to rvalues.
The one huge problem I've had with lack of rvalue references is with
arithmetic operators:
struct M
{
M opAdd(const ref M other) const {...}
}
M m;
auto m2 = (m + m) + m; // ok!
auto m3 = m + (m + m); // error!
This is crap.
If 'auto ref' gets accepted for non-template functions, it goes away.
With M as you show, returning ref doesn't work so that example I was
going to suggest doesn't work.
In my code base, I have actual comments that explain why I have ordered
certain operations the way I did!
But we have more problems than just rvalue references. The compiler
doesn't "see through" structs to know whether something is an lvalue or an
rvalue.
Consider writing your own pointer type:
struct T
{
int *x;
void opUnary(string op)() if (op == "++") {++(*x);}
}
int x;
T foo()
{
return T(&x);
}
void main()
{
auto t = foo;
t++; // ok
foo++; // Error: foo() is not an lvalue
}
That should not be an error, or I should at least be able to tell the
compiler "this is NOT an rvalue, even if it seems like one".
-Steve