
"Andrea Torsello" <torsello@dsi.unive.it> writes:
"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.
My point is that if you disable the library mechanisms that make direct initialization move instead of copy from rvalues: X a(source()); // a case you're explicitly not handling then the sink(source()) example compiles in strict mode. The default setting of my library is now configured that way for comeau.
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
IIRC I hadn't even posted my thing a couple of months ago(?)
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.
Can you please show a succinct example of "less interactions" so that I can do a comparison?
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.
As stated before, no it doesn't. Please test my code first and make claims about it later.
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.
Not entirely. Your approach entails some code duplication between the first two overloadsq. I guess the first f can be: void f(X& x) { X::constant(x); } But then what happens when f takes two or three arguments, both of which might be movable rvalues? I see an exponential explosion of overloads coming.
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.
What macro tricks? I only use those for the copy ctor and assignment operator because those may otherwise entail duplicating the function body.
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),
I'll ignore that one.
but less interactions with orthogonal language features the user should know about.
I'm still interested in seeing how that happens.
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.
I'm afraid not...
The only compiler I have seen not performing the optimization is Comeau in strict mode.
...and hence, all the EDG-based compilers do the same thing unless they're trying to emulate microsoft.
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.
Sorry, you wrote: "I chose to keep the temporary and constant subtypes from mojo because they allow me to discriminate between const values, non-const rvalues and non-const rvalues. The lack of this capability was the major problem I had with David Abrahams' move." I'm still trying to understand why it's a problem. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com