The following works for std::thread. It prints 10 as output, which is what I desire.
void foo(std::unique_ptr<int> && in) {
std::cout << *in;
}
int main(){
auto in = std::make_unique<int>(10);
std::thread t(foo, std::move(in));
t.join();
}
But, similar attempt with Boost 1.72 fails to compile
void foo(std::unique_ptr<int> && in) {
std::cout << *in;
}
int main(){
auto in = std::make_unique<int>(10);
boost::thread t(foo, std::move(in));
t.join();
}
Error : note: copy constructor of 'list1<boost::_bi::value<std::unique_ptr<int>>>' is implicitly deleted because base class 'storage1<boost::_bi::value<std::unique_ptr<int>>>' has a deleted copy constructor template< class A1 > class list1: private storage1< A1 >
I find this surprising, because the documentation for boost::thread states the following :
Thread Constructor with arguments template <class F,class A1,class A2,...> thread(F f,A1 a1,A2 a2,...);
Preconditions: F and each An must be copyable or movable.
Since I am passing a std::unique_ptr as argument, I am meeting the 'movable' criterion. So, I wonder why is boost thread constructing the std::unique_ptr? Shouldn't it move the std::unique_ptr into the thread object, and then move it further into the thread function like the implementation for std::thread does?
Per documentation,
boost::threaduses the arguments in exactly the same wayboost::binddoes, and this combination of function and argument is unsuitable forboost::bind(and forstd::bindfor that matter).std::threadis more robust than eitherstd::bindorboost::bind.If you need to move the argument to
foo, you need to wrap it in a function or a lambda that accepts it by non-const lvalue reference and moves it tofoo. Otherwise, just changefooto accept a non-const lvalue reference argument.