Объект удален из-за конструктора перемещения

Я пытаюсь создать функцию, выполняющуюся в отдельном потоке, который
читает из последовательного порта. Но у меня проблемы с передачей соединения
в тему. Я сократил свой код до следующего примера:

#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

Сообщение об ошибке совершенно ясно. Я пытаюсь использовать объект
который не существует, потому что он был удален из-за
объявление конструктора перемещения. Но я все еще не понимаю
что здесь происходит и как это сделать правильно. Может кто то
просветите меня?

1

Решение

Вы не правильно читаете ошибку. Это говорит вам, что конструктор копирования из boost::asio::basic_serial_port является deleteд. Это означает, что конструктор копирования не может быть использован. Это не имеет ничего общего с удаляемыми объектами. Причина, по которой конструктор копирования deleted, потому что определен конструктор перемещения.

Если вам действительно нужно передать ссылку на 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) {}
3

Другие решения

Простое исправление (я считаю, непроверенное) заключается в использовании ссылочной оболочки (если вам действительно нужно поддерживать оба объекта в 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,

2

По вопросам рекламы [email protected]