Boost logo

Boost :

From: Rani Sharoni (rani_sharoni_at_[hidden])
Date: 2004-02-09 04:08:54

David Abrahams wrote:
> "Rani Sharoni" <rani_sharoni_at_[hidden]> writes:
>> The problem with reference binding using conversion
>> operator/constructor(i.e. X const& r = X()) is addressed in active
>> DR #291 (see Mr. Adamczyk note)
> I'm not really sure what to make of that text.

I'll try to elaborate on that. 8.3.5/5 states that when binding class
r-value to a const reference there is a possibility to introduce additional
const temporary from the r-value and then bind it to the reference (which
might, recursively, introduce, yet additional temporary).

The question is how to construct this additional const temporary which,
according to TC1 #171, is an r-value. Now we are back to Steve Adamczyk
comment in DR #291 (and According to that comment
the copy constructor requirement was explicitly removed to allow template
converting constructors which is *not* copy-constructor. This relaxation
also (accidentally?) allows other converting constructors since they are as
good as template converting constructor in context of copy initialization
from the same type.

This means that X const& r = X() might produce the following code:
1) Construct additional const temporary using X::X(ref) which requires call
to the conversion operator. This is allowed since the initialization is from
the same type.
2) Repeat X >= 0 times: construct additional const temporary from the const
3) Bind the final r-value to the reference

The fact that the additional temporary is const might, theoretically,
encourage the optimizer to generate faster code but AFAIK no C++ optimizer
is actually aware about the existence of C++ const and *ignore* it. Anyway,
we don't really care about this elided coping constraint since if compiler
actually makes additional coping then it probably has very good reason:
X const& r = true ? X() : X(); // VC and GCC introduce additional r-value
using the "r-value" move constructor.

>> and AFAICT it was discussed during the MoJo days.
> Yep. I knew about it then, but it's so easy forgotten when you're
> hunting for the elusive "move"

I think that MoJo also achived the "move" goal but your solution is more

>> IMHO the current standard explicitly allows it (per 8.5.3/5/2/1) and
>> EDG is not very consistent about it:
>> auto_ptr<Base> const& r = auto_ptr<Derived>(); // accepted by EDG
>> auto_ptr<Base> const& r = auto_ptr<Base>(); // rejected by EDG
> I believe that those two cases use different rules. In the first case
> you have an implicit conversion, while in the second case you only
> have copy initialization.

I just presented this case to show that even EDG has problems with
The first case is obviously forbidden by TC1 #84, which most of the times
EDG and all compilers respects.
The second case is our case and it is, IMO, explicitly allowed.

