Le 08/02/13 19:01, Jeffrey Lee Hellrung, Jr. a écrit :
On Thu, Feb 7, 2013 at 11:46 PM,
Szymon Gatner <szymon.gatner@gmail.com>
wrote:
2013/2/8 Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com>:
>
> This looks like an error in the
future_traits<T>::init overload set...it's
> missing an overload that a T const & can bind
to (in the second argument).
>
> Also, I think it would be an improvement if
set_value_at_thread_exit was
> able to catch rvalues as emulated rvalue
references (when true rvalue
> references are unavailable) rather than as
lvalue-reference-to-const.
>
Yes indeed, there is an overload resolution ambiguity.
Strictly speaking, it isn't an ambiguity that's
causing the compiler failure, it's that the eligible
overload set is empty.
You are right.
I
guess movable
/ emulation stuff in Thread is more difficult to
manage since it
maintains 2 move emulations (original one from Thread
and Move).
Yes :( I can imagine the maintenance nightmare for
Vicente.
I don't know if I've missed something really relevant of
Boost.Move, but only with this emulation I have a lot of
difficulties as not only Boost.Thread defines Movable types,
but it offers interfaces with functions that can be movable
and that accept copyable/movable arguments and that can
return movable types.
Move
already provides BOOST_RV_REF(T) macro which is
T&& on compiler that
support it and rv<T>& when emulating and
this imho is the argument
type future_traits<T>::init() should use to
disambiguate.
Ideally, but the present implementation of
set_value_at_thread_exit precludes init capturing by
rvalue reference, AFAICT.
Jeffrey I believe the problem comes from the fact that I
have added two overloads for set_value_at_thread_exit and
the copy overload is instantiated when using a move-only
class
void set_value_at_thread_exit(const T &
result_){...} // this instantiation with a MoveOnly class
results in a compiler error
void
set_value_at_thread_exit(BOOST_THREAD_RV_REF(T)
result_){...}
Is
the original move emulation even still needed in
Thread code.
Using Boost.Move is some kind of breaking change respect to
the old one. I'm fully for discarding the old emulation, but
I would like to hear what others thing.
I think there are subtle differences, perhaps not
all of which have been worked out or discovered yet.
I don't think the problem comes from trying to manage 2 move
emulations, but of course I might be wrong.
anyway, I will see if I can fix it or otherwise I would
restraint the use of _at_thread_exit functions to the
compilers supporting them completely.
Vicente, here's some tips on how to improve the robustness
of the code when compiling without rvalue references (i.e.,
C++03):
If you know a function is going to receive only lvalues or
*emulated* rvalue references, it's sufficient to use a T &
parameter: [[template< class T > void f(T & x);]]
(Just be careful you don't accidentally move x; you may need
to wrap some uses of x as [[as_lvalue(x)]] to avoid that.)
This is the appropriate case for functions that receive
results of boost::forward; I think future_traits::init falls
in this category.
If a function is designed to accept both lvalues *and*
rvalues *of an a priori known type T*, and you want to be able
to capture rvalues by emulated rvalue reference (when
appropriate), then you need have 2 cases:
- T is not Boost.Move-enabled: 1 overload is probably
sufficient (if you don't care about constness): [[void f(T
const &);]]
- T is Boost.Move-enabled: 2 overloads are necessary:
[[void f(rv<T> &);]] and [[template< class U >
void f(U &);]]
Lastly, if a function is designed to accept both lvalues
and rvalues of *any* type, and you want to be able to capture
any rvalue by emulated rvalue reference when possible, you
need 3 overloads, and even then it's not always possible (if
the function return type depends on the parameter type, you're
probably SOL). This is much more involved, so I won't go into
detail here, as I think the issues relevant to this thread
fall into one of the two cases above.
If you want more detailed help (e.g., patches), we can take
this offline.