# How to Use asio::redirect_disposition for Operation Redirection

> Master asio::redirect_disposition to capture operation outcomes like error codes or exceptions. Learn how this completion-token adapter simplifies asynchronous error handling in C++.

- Repository: [chriskohlhoff/asio](https://github.com/chriskohlhoff/asio)
- Tags: how-to-guide
- Published: 2026-07-17

---

**`asio::redirect_disposition` is a completion-token adapter that captures the disposition (error code or exception pointer) from an asynchronous operation into a user-provided variable while forwarding remaining arguments to the original handler.**

The `redirect_disposition` utility in the [chriskohlhoff/asio](https://github.com/chriskohlhoff/asio) repository provides a clean mechanism for intercepting operation outcomes without altering your handler's signature. This pattern is particularly useful when you need to inspect error conditions separately from your main completion logic or when integrating with existing code that expects error codes in specific variables.

## What is asio::redirect_disposition?

`asio::redirect_disposition` acts as a **completion token adapter** that sits between an asynchronous operation and its handler. Unlike `redirect_error`, which throws or returns errors directly, `redirect_disposition` captures the first argument of a completion handler—typically an `asio::error_code` or `std::exception_ptr`—into a reference variable you provide.

The mechanism consists of three core components defined in [`include/asio/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/redirect_disposition.hpp):

- **`redirect_disposition_t`** – A thin wrapper storing the original completion token and a reference to the destination variable
- **`partial_redirect_disposition`** – A higher-order token that binds the destination variable, enabling the syntax `asio::redirect_disposition(my_error)(token)`
- **`async_result` specialization** – Defined in [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp), this adapts the wrapper into a real handler for any async operation

## How asio::redirect_disposition Works Internally

### The Adapter Components

When you invoke `asio::redirect_disposition(ec)`, the function returns a `partial_redirect_disposition` instance. When this partial token is later combined with a real completion token (such as `asio::use_future` or a custom handler), the `operator()` creates a `redirect_disposition_t<CompletionToken, Disposition>` holding both the original token and a reference to your variable.

```cpp
asio::error_code ec;
auto token = asio::redirect_disposition(ec);  // partial_redirect_disposition
auto wrapped = token(asio::use_future);        // redirect_disposition_t

```

### Handler Transformation

The `async_result` specialization for `redirect_disposition_t` constructs a `detail::redirect_disposition_handler<Disposition, Handler>` that intercepts the operation's completion. This handler:

1. Stores a reference to the destination `Disposition& d_`
2. Holds the original handler (`Handler handler_`)
3. Provides overloads of `operator()` that forward arguments unchanged when the first argument is **not** a `Disposition`, or capture the first argument into `d_` when it **is** a `Disposition`

The implementation in [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp) uses `redirect_disposition_signature` templates to rewrite the operation's completion signature, effectively removing the disposition argument from the user-visible signature while preserving the remaining parameters.

### Exception Pointer Handling

When the destination type is `std::exception_ptr`, the handler automatically converts any disposition (such as an `error_code`) into an exception pointer via `disposition_traits<>::to_exception_ptr`. This allows uniform error handling regardless of the underlying error representation.

```cpp
std::exception_ptr ep;
timer.async_wait(asio::redirect_disposition(ep));

```

## Practical Examples

### Capturing error_code

The most common use case involves capturing an `asio::error_code` into a variable for later inspection:

```cpp
asio::io_context ctx;
asio::system_timer t(ctx, std::chrono::seconds(0));
asio::error_code ec = asio::error::would_block;  // Pre-set to known state

t.async_wait(asio::redirect_disposition(ec));
ctx.run();

// After run(), ec contains the operation's error (or success code)
if (ec) {
    std::cerr << "Timer error: " << ec.message() << "\n";
}

```

### Capturing std::exception_ptr

For exception-based error handling, redirect to an `std::exception_ptr`:

```cpp
std::exception_ptr ex;
t.async_wait(asio::redirect_disposition(ex));
t.cancel();  // Force an error
ctx.run();

// ex now holds a std::exception_ptr describing the aborted operation
if (ex) {
    try {
        std::rethrow_exception(ex);
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }
}

```

### Combining with Custom Handlers

You can redirect the disposition while still using a custom completion handler:

```cpp
struct my_handler {
    void operator()(int) const {
        std::cout << "Handler called with int argument\n";
    }
};

asio::error_code ec;
t.async_wait(asio::redirect_disposition(
    asio::bind_executor(ctx.get_executor(), my_handler()), ec));

```

### Using with Deferred Tokens

The adapter works seamlessly with `asio::deferred` for composing asynchronous operations:

```cpp
t.async_wait(asio::redirect_disposition(ec))(asio::deferred)([](int result) {
    // Handle result here; error already captured in ec
});

```

## Summary

- **`asio::redirect_disposition`** captures operation dispositions (error codes or exception pointers) into user-provided variables without altering handler signatures
- The implementation relies on `redirect_disposition_t`, `partial_redirect_disposition`, and specialized `async_result` templates found in [`include/asio/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/redirect_disposition.hpp) and [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp)
- The handler adapter automatically converts `error_code` to `std::exception_ptr` when the destination type requires it
- This pattern enables flexible error handling when integrating with existing codebases or when you need to inspect errors separately from completion logic

## Frequently Asked Questions

### What is the difference between asio::redirect_disposition and asio::redirect_error?

**`asio::redirect_error`** modifies the completion signature to return the error code as a function result, while **`asio::redirect_disposition`** captures the error into a reference variable while keeping the rest of the handler signature intact. According to the source code in [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp), `redirect_disposition` is more flexible for cases where you want to capture the error but still receive other completion arguments in your handler.

### Can I use asio::redirect_disposition with any asynchronous operation?

Yes, the `async_result` specialization in [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp) makes `redirect_disposition` compatible with any Asio asynchronous operation that follows the standard completion token protocol. The adapter rewrites the completion signature using `redirect_disposition_signature` templates to ensure type safety regardless of the specific operation.

### How does the exception_ptr conversion work in asio::redirect_disposition?

When the destination type is `std::exception_ptr`, the `detail::redirect_disposition_handler` automatically converts the disposition using `disposition_traits<Disposition>::to_exception_ptr`, as implemented in [`include/asio/impl/redirect_disposition.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/impl/redirect_disposition.hpp). This allows you to capture operation failures as exception pointers even when the underlying operation reports errors via `error_code`.

### Can I combine asio::redirect_disposition with other completion tokens like use_future?

Absolutely. The `partial_redirect_disposition` class provides an `operator()` that accepts any completion token, creating a `redirect_disposition_t` that wraps the original token. This means you can write `asio::redirect_disposition(ec)(asio::use_future)` to capture errors into `ec` while having the operation return a `std::future` for the remaining arguments.