Reference: https://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept/overload1.html
boost::asio::ip::tcp::acceptor acceptor(io_service);
...
boost::asio::ip::tcp::socket socket(io_service);
// you have to initialize socket with io_service first before
//you can use it as a parameter on async_accept.
acceptor.async_accept(socket, accept_handler);
Reference:
https://github.com/vinniefalco/CppCon2018/blob/master/listener.cpp
listener:: listener(
net::io_context & ioc,
tcp::endpoint endpoint,
std::shared_ptr < shared_state >
const & state): acceptor_(ioc), socket_(ioc), state_(state) {
// Accepts incoming connections and launches the sessions
class listener : public std::enable_shared_from_this<listener>
{
tcp::acceptor acceptor_;
tcp::socket socket_;
...
}
// Handle a connection
void listener:: on_accept(error_code ec) {
if (ec)
return fail(ec, "accept");
else
// Launch a new session for this connection
std::make_shared < http_session > (
std::move(socket_), // socket_ is moved here?
state_) -> run();
// Accept another connection
acceptor_.async_accept(
socket_, // why we still can use it here?
[self = shared_from_this()](error_code ec) {
self -> on_accept(ec);
});
}
Based on my understanding, std::move(socket_)
allows the compiler to cannibalize socket_
. In other word, the listener::socket_
originally initialized by socket_(ioc)
will become uninitialized.
Question> How can we give an uninitialized socket_
to acceptor_.async_accept
?
Thank you
It all depends on the implementation of the types.
We can loosely describe the intent of a move as "the compiler is allowed to cannibalize". But really, for user-defined types we're going to have to tell it how to do that, exactly.
In language "doctrine" a moved-from object may only be assumed safe to destruct, but in practice many libraries make more lenient guarantees (e.g. keeping all the invariants, or making sure that a moved-from object is comparable to a newly constructed one).
Indeed, ASIO documents this:
Remarks
Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(const executor_type&) constructor.