The liabilities of binding rvalues to ref

Steven Schveighoffer schveiguy at yahoo.com
Thu May 9 18:53:05 PDT 2013


On Thu, 09 May 2013 20:38:47 -0400, Manu <turkeyman at gmail.com> wrote:

> What were the arguments again against ref const()? You're talking about
> making it clear that the function isn't planning on mutating the given
> rvalue...
> I understand that const is stronger than C++, but is it actually a
> deal-breaker? It's the most logical fit here.

the counter-argument goes something like this:

struct VeryLarge
{
    int[10] buffer;
    VeryLarge *next;
}

So let's say you build a VeryLarge and return it, on the stack.  Return by  
value.

VeryLarge buildOne(someArguments);

OK, you now want to assign it to a property:

class X
{
    private VeryLarge _vl;
    @property void vl(ref VeryLarge otherValue) { _vl = otherValue;}
}

X x = new X;

x.vl = buildOne(...);

If we make otherValue const, then we can't assign because of the  
indirection.

It's a tenuous argument, and I may not have made it in the best way, but  
the bottom line is that const is overly restrictive in this case.  We're  
passing by ref because we don't want to incur the copy penalty *twice*.   
If we make it const, we've added an incorrect restriction.

The solution, ironically, is to take VeryLarge by value as an overload.   
This will simply do a move, and since it's already on the stack, no extra  
copy is made.

So we NEED it to be mutable, and we don't want to restrict ourselves from  
accepting rvalues.

So the above works fine as ref, for r and l values, because we are just  
trying to copy the data.  It's when you specifically are passing by ref to  
modify the data that you want to reject rvalues.

As the original post in this thread pointed out, it's the way a library  
can alter another author's intention that causes problems.

I have another idea, but I need to put it at the top so it's not lost :)

-Steve


More information about the Digitalmars-d mailing list