Destructors, const structs, and opEquals

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Dec 10 13:17:07 PST 2010


On 12/10/10 1:10 PM, Steven Schveighoffer wrote:
> 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?

That is correct. There are a couple of related bug reports 
(http://d.puremagic.com/issues/show_bug.cgi?id=4668, 
http://d.puremagic.com/issues/show_bug.cgi?id=4258) so I'm not worried 
about the problem being forgotten.

We all need to think about this a bit more because it's related to 
another issue that I'm still losing sleep over: should we promote cheap 
copy construction throughout D or not?


Andrei


More information about the Digitalmars-d mailing list