
"David Abrahams" <dave@boost-consulting.com> writes:
By the way, if you are willing to give up on move semantics from direct initialization, my technique will work in Comeau strict mode just as well as yours. Nothing about what you did will get around that problem; it seems to be a fact of current EDG compilers that in strict mode direct initialization from an rvalue will only ever use an ordinary (T const&) copy ctor.
tested void sink(X const &); X source(); void foo() { sink(source()); } on Comeau strict does not compile... everywhere else it does.
Please do. Also please use the latest version of the code in the sandbox to test against.
Last test was a couple of months ago when I was working activly on this, will do on most recent version I can find As I said on another message, my moving class was parametrized on templated type Tp and had a converting constructor and operator = template<class U> explicit X(X<U> const &); there is the solution template<class U> explicit X(X<U> const &, enable_if_different<U,Tp,char>::type=0); but adds extra requirements on unrelatd features. The same applies to the enable_if_same<T const, X const, void>::type return type for non temporary overloaded functions. It looks like my approach doesn't do anything your approach cannot do (not surprisingly since the only difference is in the technique I use to make X(X const &) less "priviledged" than the other constructors), but it appears to have less interactions with other language features. And hence less requirements on the library user.
Actually I'm not sure what I was trying to say anymore. I can state that my library already allows
sink(source());
to work transparently with move semantics on all compilers I've tested on.
as stated before if sink is "void sink(X const &);" Comeau in strict mode complains that there is no X(X const &) constructor.
Sorry, that wans just a mistake; it isn't convertible to anything. I meant:
template <class T> // lvalues typename enable_if_same<T const, X const, void>::type f(T&);
void f(move_from<X>); // temporaries
Oh, OK that would work with operators as well, still with my approach it would be: void f(X&); void f(X::constant); void f(X::temporary); which, to me, seems easier from the user perspective. Clearly, this is just a matter of taste.
Exactly. Or you could just use explicit instantiation. BTW I assume you mean "templated function".
Yes sorry.
It's no worse a problem than replacing what should be a reference paramter with another type that can be constructed by implicit conversion. You still cut off the possibility of user-defined conversions.
Yes. I was not claiming that forcing a templated function was an unsurmoutable problem, obviously there are ways aroud it. But think from the perspective of the user: even if you hide the details of the function definition with macro tricks, suddenly the user cannot keep the function on a separate compilation unit unless the macro manages to perform the explicit instantiation as well, which would be hard since you should explicitly instantiate two specializations: one for type X and one for type X const.
I don't see any advantages yet.
Nothing your approach doesn't allow with some work (except Comeau not allowing to pass by const reference), but less interactions with orthogonal language featuresthe user should know about. The only problem I have encountered so far comes from X x(makeX()); calling the explicit copy constructor (X x=makeX(); does not). While in this case the approach fails to move, it is by far the easyest case for compiles to perform return value optimization. The only compiler I have seen not performing the optimization is Comeau in strict mode.
I didn't take it that way. I'm not arguing with you out of defensiveness. If you really think what you did had some advantages, I want to be convinced of them so I can change my library to be the best possible.
Glad to hear it, email are so easy to misunderstand... Sorry if I misunderstood you, I apologize, but I really wrote because I think this might be useful.
I still don't understand why you think it's important to distinguish const temporaries from const lvalues.
As you said in another post, it is not a problem to move from a const temporary (the compiler might just copy the const temporary to a non const temporary and optimize the copy away), hece you want to move from const temporaries.
Which my library does.
Never claimed it does not.
On the other hand, you should certainly not move from lvalues.
OK, but in that case I don't see why you want to distinguish const temporaries from non-const temporaries.
I don't. As a matter of fact I never really tested that before because I never returned a const temporary in my career. I added it to the test on the final version for completness, but I don't really care either way, since for the life of me I cannot find a use-case for const temporaries. Best Regards Andrea Torsello