
David Abrahams wrote:
"Rani Sharoni" <rani_sharoni@hotmail.com> 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 http://tinyurl.com/2kdtk). 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 r-value. 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 elegant.
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 initialization. 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. Rani