[cfe-commits] r67059 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/CodeGen/ lib/Sema/ test/Parser/ test/SemaCXX/

Howard Hinnant hhinnant at apple.com
Fri Mar 27 14:19:08 PDT 2009


On Mar 27, 2009, at 4:42 PM, Sebastian Redl wrote:

> Howard Hinnant wrote:
>> On Mar 23, 2009, at 1:18 PM, Douglas Gregor wrote:
>>
>>
>>> Yes, both are well-formed and both mean different things. The first
>>> one causes a direct binding (that's [dcl.init.ref]p5b1sb2), while
>>> the second one binds to a temporary.
>>>
>>> You know, I completely screwed up the example. I meant test() to be:
>>>
>>> void test(B b) {
>>>   A &ar = b; // ill-formed
>>> }
>>>
>>> *sigh*, and I think I've answer my own question. Sorry for the  
>>> noise.
>>>
>>
>> I was wondering.  Thanks for the clarification.  Yeah, with that
>> change I agree:  ill-formed.
>>
> Interestingly enough, by following the rules of N2857 (March draft) to
> the letter, this too is invalid:
>
> struct B { operator A&&(); };
>
> B b;
> A &&ar = b;
>
> The reason is in the bullet ordering. [dcl.init.ref]p5 says:
>
> -- If the reference is an lvalue reference [...]
> -> does not apply
> -- Otherwise, the reference shall be an lvalue reference to a
> non-volatile const type, or the reference shall be an rvalue reference
> and the initializer expression shall be an rvalue.
> -> b is an lvalue, so the program is ill-formed.
>
> Any sub-points of the second bullet no longer matter.
>
> I don't know if this is intentional. It feels right that only an  
> rvalue
> B should allow this conversion to be applied (after all, if that A&&  
> is
> moved from, most likely this affects B's state), but at the same  
> time I
> think invoking a user-defined conversion to a reference type on a
> temporary and then keeping that reference is a very unsafe thing to  
> do.

I don't know if it was intentional or not either.  But it is probably  
for the best.  There's a similar example in the WP:

    double&& rd4 = i;

This might could do a copy-conversion from int to an rvalue double,  
and then bind the rvalue double to rd4.  But the example explicitly  
states that it doesn't do this.  This is probably best because it  
would be confusing if:

    int i;
    double d;
    double&& rd1 = i;  // Works?
    double&& rd2 = d;  // Doesn't work?

And similarly:

struct B { operator A&&(); };  // or operator A()

A a;
B b;
A&& ar1 = b;  // Works?
A&& ar2 = a;  // Doesn't work?

-Howard




More information about the cfe-commits mailing list