|  | 
A completion token adapter is a utility that can be generically applied to a completion token, to produce a new completion token with modified behaviour. Common uses of completion token adapters include:
Asio includes a number of completion token adapters as described below.
          The bind_executor
          function adapts a completion token to imbue the completion handler with
          an associated executor.
        
          This example shows the bind_executor
          adapter applied to a lambda, to specify that the handler should execute
          in the specified strand. The arguments to the completion handler are passed
          through as-is.
        
my_socket.async_read_some(my_buffer, asio::bind_executor(my_strand, [](asio::error_code error, std::size_t bytes_transferred) { // ... }));
          When applied to completion tokens that cause the initiating function to
          produce a result, such as use_awaitable, the result is returned
          unmodified.
        
asio::awaitable<void> my_coroutine() { // ... std::size_t bytes_transferred = co_await my_socket.async_read_some(my_buffer, asio::bind_executor(my_strand, asio::use_awaitable)); // ... }
          The bind_allocator,
          bind_cancellation_slot,
          and bind_immediate_executor adapters
          work similarly, to imbue the completion handler with an associated
          allocator, associated
          cancellation slot, and associated immediate executor respectively.
        
          The redirect_error
          function adapts a completion token to capture the error_code
          produced by an operation into a specified variable. In doing so, it modifies
          the completion signature to remove the initial error_code
          parameter.
        
          This example shows the redirect_error
          adapter applied to a lambda, to specify that the error should be captured
          into my_error. The error_code is no longer passed to the
          completion handler, but the remaining arguments are passed through as-is.
        
asio::error_code my_error; // N.B. must be valid until operation completes // ... my_socket.async_read_some(my_buffer, asio::redirect_error( [](std::size_t bytes_transferred) { // ... }, my_error));
          When applied to completion tokens that cause the initiating function to
          produce a result, such as use_awaitable, the result is returned
          unmodified. However, if the operation fails, the co_await
          expression will no longer throw an exception on resumption.
        
asio::awaitable<void> my_coroutine() { // ... asio::error_code my_error; std::size_t bytes_transferred = co_await my_socket.async_read_some(my_buffer, asio::redirect_error(asio::use_awaitable, my_error)); // ... }
          The as_tuple
          adapter can be used to specify that the completion handler arguments should
          be combined into a single tuple argument.
        
          For example, the as_tuple
          adapter may be used in conjunction with use_awaitable and structured bindings
          as follows:
        
auto [e, n] = co_await my_socket.async_read_some(my_buffer, asio::as_tuple(asio::use_awaitable));
This adapter may also be used as a default completion token:
using default_token = asio::as_tuple_t<asio::use_awaitable_t<>>; using tcp_socket = default_token::as_default_on_t<tcp::socket>; // ... asio::awaitable<void> do_read(tcp_socket my_socket) { // ... auto [e, n] = co_await my_socket.async_read_some(my_buffer); // ... }
| ![[Note]](../../../note.png) | Note | 
|---|---|
| This is an experimental feature. | 
          The experimental::as_single adapter can be used
          to specify that the completion handler arguments should be combined into
          a single argument. For completion signatures with a single parameter, the
          argument is passed through as-is. For signatures with two or more parameters,
          the arguments are combined into a tuple.
        
          For example, when applied to a timer wait operation, the single error_code argument is passed directly
          to the completion handler:
        
my_timer.async_wait( asio::experimental::as_single( [](asio::error_code error) { // ... }));
When applied to a socket read operation, where the completion signature specifies two parameters, the handler is passed the result as a tuple:
my_socket.async_read_some(my_buffer, asio::experimental::as_single, [](std::tuple<asio::error_code, std::size_t> result) { // ... }));
          The append
          completion token adapter can be used to pass additional completion handler
          arguments at the end of the completion signature.
        
For example:
timer.async_wait( asio::append( [](std::error_code ec, int i) { // ... }, 42 ) ); std::future<int> f = timer.async_wait( asio::append( asio::use_future, 42 ) );
          The prepend
          completion token adapter can be used to pass additional completion handler
          arguments before the existing completion handler arguments.
        
For example:
timer.async_wait( asio::prepend( [](int i, std::error_code ec) { // ... }, 42 ) ); std::future<std::tuple<int, std::error_code>> f = timer.async_wait( asio::prepend( asio::use_future, 42 ) );
          The consign
          completion token adapter can be used to attach additional values to a completion
          handler. This is typically used to keep at least one copy of an object,
          such as a smart pointer, alive until the completion handler is called.
        
For example:
auto timer1 = std::make_shared<asio::steady_timer>(my_io_context); timer1->expires_after(std::chrono::seconds(1)); timer1->async_wait( asio::consign( [](std::error_code ec) { // ... }, timer1 ) ); auto timer2 = std::make_shared<asio::steady_timer>(my_io_context); timer2->expires_after(std::chrono::seconds(30)); std::future<void> f = timer2->async_wait( asio::consign( asio::use_future, timer2 ) );
bind_executor, bind_allocator, bind_cancellation_slot, redirect_error, as_tuple, experimental::as_single, append, prepend.