1

我正在尝试创建一个在从串行端口读取的专用线程中运行的函数。但是我无法将连接传递给线程。我将代码简化为以下示例:

#include <thread>
#include <boost/asio.hpp>

template <typename Port>
void serial_read( Port& port) {}

int main()
{
  boost::asio::io_service serial_io;
  boost::asio::serial_port port( serial_io );
  port.open( "/dev/ttyUSB0" );

  std::thread s( serial_read<boost::asio::serial_port>, port );
  return 0;
}

但是,我收到以下错误消息:

/usr/include/c++/4.7/tuple:128:25: error: use of deleted function ‘boost::asio::basic_serial_port<>::basic_serial_port(const boost::asio::basic_serial_port<>&)’
In file included from /usr/include/boost/asio.hpp:25:0,
                 from main.cpp:2:
/usr/include/boost/asio/basic_serial_port.hpp:47:7: note: ‘boost::asio::basic_serial_port<>::basic_serial_port(const boost::asio::basic_serial_port<>&)’ is implicitly declared as deleted because ‘boost::asio::basic_serial_port<>’ declares a move constructor or move assignment operator

错误信息非常清楚。我正在尝试使用一个不存在的对象,因为它由于声明了移动构造函数而被删除。但我仍然不明白这里发生了什么以及如何正确地做到这一点。有人可以启发我吗?

4

2 回答 2

3

您没有正确阅读错误。它告诉你的复制构造函数boost::asio::basic_serial_port是d delete。这意味着无法使用复制构造函数。它与被删除的对象无关。复制构造函数是deleted 的原因是定义了移动构造函数。

如果您确实需要传递对 的引用serial_read,则需要将port对象包装在 a 中reference_wrapper

std::thread s( serial_read<boost::asio::serial_port>, std::ref(port) );

但是,如果您不保留port并将其用于其他任何事情(例如将相同的port对象传递给其他线程),您应该std::move将您的port对象放入线程中:

std::thread s( serial_read<boost::asio::serial_port>, std::move(port) );

这还需要更改按值取值的serial_read定义Port

template <typename Port>
void serial_read( Port port) {}
于 2013-03-27T14:56:48.720 回答
2

简单的修复(我相信,未经测试)是使用引用包装器(如果你真的需要main在线程中和线程中维护对象):

std::thread s(&serial_read<boost::asio::serial_port>,std::ref(port));

问题是std::threadstd::bind将创建一个带有参数副本的仿函数)稍后将被使用(没有参数)。基本上上面的调用类似于:

std::thread( std::bind(&serial_read<boost::asio::serial_port>,std::ref(port)) );

绑定对象中存储了每个参数的副本,这要求参数是可复制构造的。引用包装器的使用允许复制(包装器被复制,原始对象不被复制)。

另一种选择是,如果您不需要维护port有效的对象main是从它移动,而不是复制绑定的对象中,您允许实现main.

于 2013-03-27T14:57:41.253 回答