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.