Destructors, const structs, and opEquals

Steven Schveighoffer schveiguy at yahoo.com
Fri Dec 10 13:10:58 PST 2010


On Fri, 10 Dec 2010 15:58:17 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> 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.

OK, now I get it, thanks for explaining it again :)  So essentially you  
are overriding the "no ref rvalues" rule, this is a good thing, because  
many times the compiler is too conservative in that decision.

To summarize for those looking for the C++ behavior, the equivalent would  
be:

void foo(auto ref const Widget)

right?  Well, at least when it's implemented properly :)  BTW, is there a  
bugzilla entry on this?

-Steve


More information about the Digitalmars-d mailing list