简体   繁体   English

将仅移动 function arguments 传递给 boost::thread 构造函数

[英]Passing move-only function arguments to boost::thread constructor

The following works for std::thread .以下适用于std::thread It prints 10 as output, which is what I desire.它将 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();
} 

But, similar attempt with Boost 1.72 fails to compile但是,使用 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 >

I find this surprising, because the documentation for boost::thread states the following:我觉得这很令人惊讶,因为 boost::thread 的文档说明了以下内容:

Thread Constructor with arguments template <class F,class A1,class A2,...> thread(F f,A1 a1,A2 a2,...);带有 arguments 模板的线程构造函数 <class F,class A1,class A2,...> thread(F f,A1 a1,A2 a2,...);

Preconditions: F and each An must be copyable or movable.前提条件:F 和每个 An 必须是可复制的或可移动的。

Since I am passing a std::unique_ptr as argument, I am meeting the 'movable' criterion.由于我将std::unique_ptr作为参数传递,因此我满足“可移动”标准。 So, I wonder why is boost thread constructing the std::unique_ptr ?所以,我想知道为什么 boost 线程构造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?它不应该像std::thread的实现那样将 std::unique_ptr 移动到线程 object 中,然后将其进一步移动到线程 function 中吗?

Per documentation, boost::thread uses the arguments in exactly the same way boost::bind does, and this combination of function and argument is unsuitable for boost::bind (and for std::bind for that matter).根据文档, 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 is more robust than either std::bind or boost::bind . std::threadstd::bindboost::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 to foo .如果您需要将参数移动到foo ,则需要将其包装在 function 或 lambda 中,通过非常量左值引用接受它并将其移动到foo Otherwise, just change foo to accept a non-const lvalue reference argument.否则,只需更改foo以接受非常量左值引用参数。

Looks like a bug in Boost.Thread documentation.看起来像Boost.Thread文档中的错误。 By default it doesn't support move-only arguments since it passes them through to boost::bind by-value instead of forwarding.默认情况下,它不支持仅移动 arguments 因为它将它们传递给boost::bind按值而不是转发。

But there's a flag BOOST_THREAD_PROVIDES_VARIADIC_THREAD that enables boost::thread rvalue-constructors.但是有一个标志BOOST_THREAD_PROVIDES_VARIADIC_THREAD可以启用boost::thread右值构造函数。 It is set automatically when another poorly documented variable, BOOST_THREAD_VERSION > 4.当另一个记录不充分的变量BOOST_THREAD_VERSION > 4 时,它会自动设置。

#define BOOST_THREAD_VERSION 5
#include <boost/thread.hpp>
. . .

Live demo现场演示

Another possible workaround is to use a lambda.另一种可能的解决方法是使用 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();
}

Live demo 2现场演示 2

The boost thread library uses boost bind, and boost bind assumes you can call the callable repeatedly, so doesn't move out of it. boost线程库使用boost bind,boost bind假设你可以重复调用callable,所以不要移出它。 You can fake it.你可以伪造它。

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);
};

then然后

auto in = std::make_unique<int>(10);
boost::thread t(foo, move_it(in));
t.join();

what this does is wrap in in a type that, when cast to T , moves instead of copies.它的作用是包装in一个类型中,当它转换为T时,它会移动而不是复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM