Я пытаюсь создать функцию, выполняющуюся в отдельном потоке, который
читает из последовательного порта. Но у меня проблемы с передачей соединения
в тему. Я сократил свой код до следующего примера:
#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
Сообщение об ошибке совершенно ясно. Я пытаюсь использовать объект
который не существует, потому что он был удален из-за
объявление конструктора перемещения. Но я все еще не понимаю
что здесь происходит и как это сделать правильно. Может кто то
просветите меня?
Вы не правильно читаете ошибку. Это говорит вам, что конструктор копирования из boost::asio::basic_serial_port
является delete
д. Это означает, что конструктор копирования не может быть использован. Это не имеет ничего общего с удаляемыми объектами. Причина, по которой конструктор копирования delete
d, потому что определен конструктор перемещения.
Если вам действительно нужно передать ссылку на serial_read
, вам нужно обернуть port
объект в 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) {}
Простое исправление (я считаю, непроверенное) заключается в использовании ссылочной оболочки (если вам действительно нужно поддерживать оба объекта в main
и в теме)
std::thread s(&serial_read<boost::asio::serial_port>,std::ref(port));
Проблема в том, что std::thread
(как std::bind
создаст функтор с копией аргументов), который впоследствии будет использоваться (без аргументов). В основном вызов выше похож на:
std::thread( std::bind(&serial_read<boost::asio::serial_port>,std::ref(port)) );
в связанный В объекте сохраняется копия каждого из аргументов, что требует, чтобы аргументы были копируемыми. Использование эталонной оболочки допускает копирование (оболочка копируется, а оригинальный объект — нет).
Другой вариант, если вам не нужно поддерживать port
объект действителен в main
это перейти от него, чтобы вместо копирование в связанный объект, который вы позволяете реализацию переехать от объекта в main
,