Destructors, const structs, and opEquals

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Dec 10 12:58:17 PST 2010


On 12/10/10 12:46 PM, Steven Schveighoffer wrote:
> On Mon, 06 Dec 2010 08:34:20 -0500, Steven Schveighoffer
> <schveiguy at yahoo.com> wrote:
>
>> On Sun, 05 Dec 2010 09:18:13 -0500, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>
>>> On 12/5/10 12:04 AM, Steven Schveighoffer wrote:
>>>> I'm totally confused. I thought the point of auto ref was to pass by
>>>> value if it's an rvalue (since the data is already on the stack). If
>>>> this is not the case, then why not just make ref work that way? Why
>>>> wouldn't I mark all my functions as auto ref to avoid being pestered by
>>>> the compiler?
>>>
>>> Because you sometimes do care about dealing with a true lvalue.
>>> Consider:
>>>
>>> void bump(ref int x) {
>>> ++x;
>>> }
>>>
>>> Then:
>>>
>>> unsigned int y;
>>> bump(y); // you don't want this to go through
>>> short z;
>>> bump(z); // you don't want this to go through
>>> int w;
>>> bump(w * 2); // you don't want this to go through
>>
>> Right.
>>
>> OK, so now I understand what you are saying, but now I don't
>> understand why const ref is such a mistake. Before you explained it
>> was because when you pass an rvalue by ref, it's much more expensive,
>> so auto ref passes by ref if it's an lvalue and by value if it's an
>> rvalue. At least that's what I understood.
>>
>> With const ref, you get the same behavior, plus you are guaranteed
>> that the code isn't going to do something stupid (like modify a value
>> that will be thrown away at the end).
>
> Not sure if this got lost in the noise, I'm still puzzled about this...

Sorry, indeed I haven't seen it.

The problem with binding rvalues to const ref is that once that is in 
place you have no way to distinguish an rvalue from a const ref on the 
callee site. If you do want to distinguish, you must rely on complicated 
conversion priorities. For example, consider:

void foo(ref const Widget);
void foo(Widget);

You'd sometimes want to do that because you want to exploit an rvalue by 
e.g. moving its state instead of copying it. However, if rvalues become 
convertible to ref const, then they are motivated to go either way. A 
rule could be put in place that gives priority to the second 
declaration. However, things quickly get complicated in the presence of 
other applicable rules, multiple parameters etc. Essentially it was 
impossible for C++ to go this way and that's how rvalue references were 
born.

For D I want to avoid all that aggravation and have a simple rule: 
rvalues don't bind to references to const. If you don't care, use auto 
ref. This is a simple rule that works promisingly well in various 
forwarding scenarios.


Andrei



More information about the Digitalmars-d mailing list