Rvalue references - The resolution

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon May 6 07:40:06 PDT 2013


On 5/6/13 10:31 AM, Steven Schveighoffer wrote:
> On Mon, 06 May 2013 10:05:48 -0400, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org> wrote:
>
>> On 5/6/13 12:48 PM, Steven Schveighoffer wrote:
>>> On Mon, 06 May 2013 06:43:38 -0700, Andrei Alexandrescu
>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>
>>>> I think we can technically make the overloading work while also
>>>> allowing binding rvalues to ref. But that wouldn't help any. Consider:
>>>>
>>>> ref int min(ref int a, ref int b) { return b < a ? b : a; }
>>>> ...
>>>> int x;
>>>> fun(min(x, 100));
>>>>
>>>> Here the result of min may be bound to an lvalue or an rvalue
>>>> depending on a condition. In the latter case, combined with D's
>>>> propensity to destroy temporaries too early (immediately after
>>>> function calls), the behavior is silently undefined; the code may pass
>>>> unittests.
>>>
>>> Wouldn't the new runtime check fix this?
>>
>> Depends how you define "fix". It would be a possibly rare bounds check
>> violation on completely innocuous code.
>
> By "completely innocuous" you mean valid? I don't think the above is valid.

I meant valid-looking.

>>>> This is a known issue in C++. Allowing loose binding of rvalues to ref
>>>> not only inherits C++'s mistake, but also adds a fresh one.
>>>
>>> I thought C++ would handle this kind of code. I remember being able to
>>> use references to rvalues in ways that were unintuitive, but not
>>> undefined.
>>
>> template <class T> const T& min(const T& a, const T& b) {
>> return b < a ? b : a;
>> }
>> ...
>> int x = ...;
>> auto & weird = min(x, 100);
>>
>> Have a nice day :o).
>
> It seems to compile and work for me, but I don't know what the point is,
> since you are being mysterious :)

If x > 100, the code is saving a reference to a destroyed temporary. If 
you couldn't see it, how many do you expect would see similar issues in 
even simpler and cleaner D code?

> A long time ago I wrote a logging feature for C++ that returned an
> rvalue (maybe it was an rvalue reference, it was a long time ago, and I
> don't have the code anymore). That would collect log messages via the <<
> operator, and then when the line was through, the destructor would
> output that line to the logger. The logging object fetched would either
> be a dummy no-output object, or a real logger, depending on the logging
> level selected. If the logger was disabled, no message was constructed,
> making it somewhat lazy (any expressions in the line would obviously be
> executed, just like any standard logger). It worked without a hitch as
> long as we used it. The rvalue stayed allocated and valid throughout the
> whole line, even though it was passed into each << operation by reference.

Not relevant.


Andrei


More information about the Digitalmars-d mailing list