[英]Passing move-only function arguments to boost::thread constructor
以下适用于std::thread
。 它将 10 打印为 output,这是我想要的。
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();
}
但是,使用 Boost 1.72 的类似尝试无法编译
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 >
我觉得这很令人惊讶,因为 boost::thread 的文档说明了以下内容:
带有 arguments 模板的线程构造函数 <class F,class A1,class A2,...> thread(F f,A1 a1,A2 a2,...);
前提条件:F 和每个 An 必须是可复制的或可移动的。
由于我将std::unique_ptr
作为参数传递,因此我满足“可移动”标准。 所以,我想知道为什么 boost 线程构造std::unique_ptr
? 它不应该像std::thread
的实现那样将 std::unique_ptr 移动到线程 object 中,然后将其进一步移动到线程 function 中吗?
根据文档, boost::thread
使用 arguments 的方式与boost::bind
完全相同,并且 function 和参数的组合不适合boost::bind
(也不适用于std::bind
)。
std::bind(foo, std::move(in))(); // error
boost::bind(foo, std::move(in))(); // error
std::thread
比std::bind
或boost::bind
更健壮。
如果您需要将参数移动到foo
,则需要将其包装在 function 或 lambda 中,通过非常量左值引用接受它并将其移动到foo
。 否则,只需更改foo
以接受非常量左值引用参数。
看起来像Boost.Thread文档中的错误。 默认情况下,它不支持仅移动 arguments 因为它将它们传递给boost::bind
按值而不是转发。
但是有一个标志BOOST_THREAD_PROVIDES_VARIADIC_THREAD
可以启用boost::thread
右值构造函数。 当另一个记录不充分的变量BOOST_THREAD_VERSION
> 4 时,它会自动设置。
#define BOOST_THREAD_VERSION 5
#include <boost/thread.hpp>
. . .
另一种可能的解决方法是使用 lambda。
void foo(std::unique_ptr<int> in) {
std::cout << *in;
}
int main() {
auto in = std::make_unique<int>(10);
boost::thread t([in = std::move(in)]() mutable { foo(std::move(in)); });
t.join();
}
boost线程库使用boost bind,boost bind假设你可以重复调用callable,所以不要移出它。 你可以伪造它。
template<class T>
struct move_it_t {
T t;
operator T(){ return std::move(t); }
};
template<class T>
move_it_t<typename std::decay<T>::type> move_it(T&& t)
return std::move(t);
};
然后
auto in = std::make_unique<int>(10);
boost::thread t(foo, move_it(in));
t.join();
它的作用是包装in
一个类型中,当它转换为T
时,它会移动而不是复制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.