繁体   English   中英

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

[英]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::threadstd::bindboost::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();
}

现场演示 2

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.

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