2

I think in the following code should work but it generates a compilation error:

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>'

It seems that the move constructor is not called implicitly.

#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;
}

I also tried to define BOOST_ASIO_HAS_MOVE as suggested in this question but it didn't work.

Is there any workaround for this?

Experimented with VS2013 update 3 and boost 1.56.0.

Community
  • 1
  • 1
perimasu
  • 1,025
  • 1
  • 8
  • 16
  • The problem is that `std::thread` stores the parameters internally, which means that when the thread function is called the argument is passed *by value*. – Some programmer dude Apr 26 '15 at 13:44
  • Sorry if my answer isn't on point but I'm not 100% sure what you're trying to get at. I wrote my answer based on "I think this code should work" and then went on to explain why it doesn't and how it should. If your question isn't about creating a functioning program using boost::asio, but rather about move semantics and how they would apply some abstract concept to do with a thread taking ownership of something, then please clarify. –  Apr 26 '15 at 20:09
  • @TechnikEmpire Sorry for ambiguity. As you said, my intension was about the hehavior of move semantics when I want to move ownership of socket to Func through std::thread, not about usage of boost::asio. – perimasu Apr 27 '15 at 01:54

1 Answers1

1

This is a known bug with the compiler. The bug ticket mentions that this has been fixed in VS 2015 RTM.

As a workaround, consider creating a shim to move the socket. Here is a small example demonstrating this approach:

#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();
}

Also, be aware that some form of synchronization needs to keep the io_service alive until after the destruction of associated I/O objects.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169