As an optimisation, user-defined completion handlers may provide move constructors, and Asio's implementation will use a handler's move constructor in preference to its copy constructor. In certain circumstances, Asio may be able to eliminate all calls to a handler's copy constructor. However, handler types are still required to be copy constructible.
When move support is enabled, asynchronous that are documented as follows:
template <typename Handler> void async_XYZ(..., Handler handler);
are actually declared as:
template <typename Handler> void async_XYZ(..., Handler&& handler);
The handler argument is perfectly forwarded and the move construction occurs
within the body of async_XYZ()
. This ensures that all other
function arguments are evaluated prior to the move. This is critical when
the other arguments to async_XYZ()
are members of the handler.
For example:
struct my_operation { shared_ptr<tcp::socket> socket; shared_ptr<vector<char>> buffer; ... void operator(error_code ec, size_t length) { ... socket->async_read_some(asio::buffer(*buffer), std::move(*this)); ... } };
Move support is automatically enabled for g++
4.5 and
later, when the -std=c++0x
or -std=gnu++0x
compiler options are used. It may be disabled by defining ASIO_DISABLE_MOVE
,
or explicitly enabled for other compilers by defining ASIO_HAS_MOVE
.
Note that these macros also affect the availability of movable
I/O objects.