2015-04-26 2 views
2

Я думаю, что в следующем коде должны работать, но он генерирует ошибку компиляции:Move конструктор не вызывается с усилением :: ASIO :: IP :: ТСР :: сокет

error C2248: 'boost::asio::basic_io_object<SocketService,true>::basic_io_object' : cannot access private member declared in class 'boost::asio::basic_io_object<SocketService,true>' 

Кажется, что конструктор шаг не называется неявно.

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

void Func(boost::asio::ip::tcp::socket sock) {} 

int main() 
{ 
    boost::asio::io_service service; 
    boost::asio::ip::tcp::socket sock(service); 
    std::thread(Func, std::move(sock)).detach(); // error C2248 
    //Func(std::move(sock)); // OK 
    return 0; 
} 

Я также попытался определить BOOST_ASIO_HAS_MOVE как предложено в this question, но это не сработало.

Есть ли обходной путь для этого?

Экспериментировано с обновлением VS2013 3 и повышением 1.56.0.

+0

Проблема заключается в том, что 'std :: thread' хранит параметры внутри, что означает, что когда функция потока вызывается, аргумент передается * по значению *. –

+0

Извините, если мой ответ не на месте, но я не уверен на 100%, к чему вы пытаетесь добраться. Я написал свой ответ на основе «Я думаю, что этот код должен работать», а затем продолжил объяснять, почему он этого не делает и как он должен. Если ваш вопрос не о создании действующей программы с использованием boost :: asio, а скорее о семантике перемещения и о том, как они применили бы какую-то абстрактную концепцию, чтобы сделать поток, владеющий чем-то, пожалуйста, уточните. –

+0

@TechnikEmpire Извините за двусмысленность. Как вы сказали, мое намерение было связано с изменением семантики перемещения, когда я хочу переместить принадлежность сокета к Func через std :: thread, а не об использовании boost :: asio. – akarin64

ответ

1

Это известная ошибка с компилятором. В bug ticket упоминается, что это было исправлено в RTM VS 2015.

В качестве обходного пути рассмотрите возможность создания прокладки для перемещения гнезда. Вот небольшой пример demonstrating такого подход:

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

void Func(boost::asio::ip::tcp::socket) {} 

int main() 
{ 
    boost::asio::io_service io_service; 
    auto socket = std::make_shared<boost::asio::ip::tcp::socket>(
     std::ref(io_service)); 

    // Use a shim to move the socket to Func. 
    std::thread func_thread([socket]() { 
    return Func(std::move(*socket)); 
    }); 
    socket.reset(); 

    // Guarantee the io_service remains alive until after 
    // its I/O objects have been destroyed. 
    func_thread.join(); 
} 

Кроме того, следует помнить, что некоторая форму синхронизации необходимо, чтобы сохранить io_service в живых до тех пор, после разрушения связанных объектов ввода/вывода.

Смежные вопросы