
Should't the following thread_data(BOOST_RV_REF(F) f_): f(boost::move(f_))
use forward instead of move? thread_data(BOOST_RV_REF(F) f_): f(boost::forward<F>(f_))
Why the following (both) overloads are needed?
thread_data(BOOST_RV_REF(F) f_); thread_data(F const& f_);
When I submitted the patch, I thought that my handling of the forwarding was a bit awkward. As I will describe later in this email, I have submitted a new patch which uses the technique suggested by Jeffrey Lee Hellrung. That said, this discussion about the `thread_data` constructors is mostly irrelevant. `thread_data` is an internal type, and the code in the `thread` constructors already performs the lvalue/rvalue matching and calls the appropriate `thread_data` constructor.
Hrr, this is really a bad new. Could you create a Boost.Move ticket if the limitation is not documented and a ticket doesn't exists already for this issue?
As the issue has been resolved by an alternative technique, this is probably not necessary.
Could you try to run the test on trunk related to move semantics with your version?
I will do this later tonight.
Could you analyze in more detail the impact of using has_move_emulation_enabled?
I investigated further, and while I still do not fully understand the impact, it seems that it is harmless to use it in the particular case where I am using it. In the name of consistency, I have changed the code to use has_move_emulation_enabled in version 1 of the patch.
Why the following (both) overloads are needed?
thread_data(BOOST_RV_REF(F) f_); thread_data(F const& f_);
I don't know the context here, but I believe, in C++03, this would: capture-and-copy lvalues and rvalues; and capture-and-move explicitly created emulated rvalue references. Thus, true rvalues are captured as lvalues :(
`thread_data` is an internal class. Its constructors are only ever called with explicitly created rvalues (which are forwarded from the rvalues that are matched in the constructor of `thread`), or lvalues. Thus the above behaviour is not problematic.
If you don't want to compromise, you could use a different set of overloads in C++03 and C++11: [snip] I haven't tested this, but it *should* capture-and-move both true rvalues and emulated rvalue references in C++03. And if it's an emulated rvalue reference, the second overload requires 1 fewer move construction.
Thankyou for the idea!
It's a known limitation in Boost.Move, AFAIK. The above change should address this issue.
It does. I have submitted a new version of the patch that uses those overloads in the constructors of `thread` and `packaged_task`.
[snip... explicit move() and copy() ...]
I don't like this too much. Why doesn't boost::move works in this case? Could you give an example on which .copy() is needed?
boost::move will not work on rvalues. `.copy()` is needed to allow a constructor to be matched from a const rvalue.
I don't know if this point will prevent the adoption of Boost.Move by Boost.Thread. I will comeback when I do some trials. See if the aforementioned solution I gave is acceptable. It is. Thankyou!
[I like the D-style template argument delimiters!] I have no confidence in my mail client whatsoever (you can see what it did to the formatting of my message), and I was trying to avoid the template being argument delimiters being seen as HTML tags and stripped. Note also - there was an error in my original posting, what I meant was `is_convertible!(T&, boost::rv!(T)&)`.
has_move_emulation_enabled<T> should be identical to boost::is_convertible<T&, boost::rv<T>& >, no?
It isn't identical, but in the particular situation in which it is being used, I believe it has the same effect.
If the above is all accurate, then I wonder where the above 3 constructor overloads came from in the first place...?
The above is all accurate. The 3 constructor overloads originally came from the constructors that all BOOST_COPYABLE_AND_MOVABLE types have. I thought that using the same overloads would also be appropriate for a template. I was wrong (for the reasons that you gave). -- Evan Wallace