From: Andrea Torsello (torsello_at_[hidden])
Date: 2004-04-19 09:51:33
David Abrahams wrote:
> Andrea Torsello <torsello_at_[hidden]> writes:
>> No, in some implementations you can just not provide the explicit
>> constructor at all (at least gcc works well without it). If you do
>> that you do not have the direct initialization problem anymore. I
>> used the explicit keyword to use my approach with compliers like
>> Comeau that do not like if you do not provide a X(X const &)
>> constructor. I actually omitted to say this on the first iteration
>> of the sample code because I though I needed to focus on the general
>> approach. In the library I use with gcc I simply do not provide the
>> explicit copy ctor at all.
> I really understood that's what you were saying. My point was that if
> you just leave out the fancy "move ctor" overloads and provide the
> X(X const&) ctor with Comeau, the RVOs kick in and you don't get any
> suboptimal copies... except when using direct initialization. Since
> your technique punts on moving in that case anyway, it seems like
> there's really zero advantage to using the explicit copy ctor at all.
Oh, OK, if you assume that the compiler can always perform return value
optimization, you are right. But I feel there is a difference in requiring
the compiler to perform RVO on direct initialization from temporaries and
requiring the compiler to perform it every time it is possible.
Using the explicit constructor technique #2 works even with compilers that
do not support RVO, as long as you use the assignment constructor instead
of the direct copy constructor. You still need to convert to temporary in
initializer lists, since you cannot use the assigment constructor there,
but most likely you would have to do it anyway.
> The point is that if you want to use macros (or copy-and-paste) to
> generate the two overloads for (T& rhs) and (const_lvalue<T> rhs), you
> can have a problem trying to re-use the initializer list and body of
> the function because T& and const_lvalue<T> have different interfaces.
> With the appropriate conversion operator on const_lvalue,
> implicit_cast<T const&>(rhs) is the same thing in both cases and can
> be used to make initializer lists and bodies that can be reused.
Oh, right! There is probably no way around explicitly writing both
constructors, but you can avoid duplication by putting the constructor's
body in a private member function and forward from both constructors to it.
At least that is what I have been doing.
> The suboptimal copies in my measurements for "technique 2" appear
> without any use of "explicit" on the copy ctor. Please, though, take
> a close look at what the code is doing to see if I've misinterpreted
> your intention. In particular, run the move.cpp test, then turn on
> -DBOOST_IMPLICIT_MOVE_CTOR_FOR_COPYABLE_TYPES and edit the code to
> make the ctor explicit. I think you'll see that it puts us back where
> we started.
> P.S. My tests are really the best part of what I've done on this; they
> reveal so much about what the compilers are doing, and tend to find
> problem cases by testing move-only types. I really want to encourage
> you to try whatever move ideas you may have in the testing framework
> I've set up.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk