微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决将仅移动函数参数传递给 boost::thread 构造函数

以下适用于 std::thread。它打印 10 作为输出,这正是我想要的。

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 的文档说明如下:

带参数的线程构造函数 模板 线程(F f,A1 a1,A2 a2,...);

先决条件: F 和每个 An 必须是可复制或可移动的。

由于我将 std::unique_ptr 作为参数传递,因此我满足了“可移动”标准。所以,我想知道为什么 boost 线程会构造 std::unique_ptr?难道它不应该像 std::thread 的实现那样将 std::unique_ptr 移动到线程对象中,然后将其进一步移动到线程函数中吗?

解决方法

根据文档,boost::thread 以与 boost::bind 完全相同的方式使用参数,并且函数和参数的这种组合不适用于 boost::bind(对于 std::bind那件事)。

std::bind(foo,std::move(in))(); // error
boost::bind(foo,std::move(in))(); // error

std::threadstd::bindboost::bind 更健壮。

如果您需要将参数移动到 foo,您需要将它包装在一个函数或一个通过非常量左值引用接受它的 lambda 中并将其移动到 foo。否则,只需更改 foo 以接受非常量左值引用参数。

,

看起来像 Boost.Thread 文档中的错误。默认情况下,它不支持仅移动参数,因为它将它们传递给 boost::bind 按值而不是转发。

但是有一个标志 BOOST_THREAD_PROVIDES_VARIADIC_THREAD 可以启用 boost::thread 右值构造函数。当另一个记录不佳的变量 BOOST_THREAD_VERSION > 4 时,它会自动设置。

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

Live demo

另一种可能的解决方法是使用 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

,

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 时,它会移动而不是复制。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。