Re: Passing std::unique_ptr to std::thread's target
On 12 Aug., 00:02, Andy Venikov wrote:
On 08/10/2011 09:04 PM, Daniel Kr?gler wrote:
Exactly. glibc++ is using bind internally to forward the arguments to the
thread functor.
[...]
So, it looks like bind can't be used internally by thread library to
pass arguments.
Right. The easiest solution is probably to make use of make_tuple:
auto argtup = make_tuple(std::forward<Args>(args)...);
// store this thing
And later to forward it with a bit of meta programming:
template<int... Ints>
struct int_pack {};
template<int N, int... Tail>
struct make_indices : make_indices<N-1,N-1,Tail...> {};
template<int... Tail>
struct make_indices<0,Tail...> {
typedef int_pack<Tail...> type;
};
template<class IntPack> struct invoke_helper;
template<int... Indices>
struct invoke_helper<int_pack<Indices...> > {
template<class Func, class... T>
static void doit(Func&& f, std::tuple<T...> const& a) {
std::forward<Func>(f)(
std::get<Indices>(a)...
);
}
static void doit(Func&& f, std::tuple<T...> && a) {
std::forward<Func>(f)(
std::forward<typename std::tuple_element<Indices>::type>(
// ^^^^^^^ (*)
std::get<Indices>(a)
)...
);
}
// (*): this is intentionally no std::move since one of
// the Ts might be an lvalue reference.
};
...
typedef decltype(argtup) argtup_type;
constexpr int N = tuple_size<argtup_type>::value;
typedef typename make_indices<N>::type indices;
invoke_helper<indices>::doit(std::move(fun),std::move(argtup));
// no longer needed in thread/async ^^^ ^^^^^^
// hence the std::move.
(untested)
Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]