# What C++ Standards Does Asio Support? Complete Guide to Version Compatibility

> Discover which C++ standards Asio supports from C++03 to C++23. Learn how Asio leverages newer C++ features for enhanced programming with this comprehensive guide.

- Repository: [chriskohlhoff/asio](https://github.com/chriskohlhoff/asio)
- Tags: getting-started
- Published: 2026-07-16

---

**Asio supports C++03 through C++23, progressively enabling features like `std::chrono`, lambda-based handlers, and C++20 coroutines via feature-detection macros defined in [`include/asio/version.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/version.hpp).**

The Asio library (chriskohlhoff/asio) is designed to work across a wide range of C++ standards, automatically adapting to the capabilities of your compiler. Whether you are maintaining legacy codebases or building modern asynchronous applications with coroutines, Asio detects the available language features at compile time and enables appropriate code paths.

## C++ Standard Support Matrix

Asio provides tiered support for C++ standards, from pre-C++11 compilers to the latest C++23 preview features.

### C++03 (Pre-C++11)

Even on legacy compilers, Asio provides **full core functionality**. Features requiring modern language facilities are simply disabled, falling back to classic implementation patterns. No special macros are required to use Asio with C++03.

### C++11

When `__cplusplus >= 201103L` or `_MSC_VER >= 1600` is detected, Asio enables:
- `std::chrono` integration for timers
- `std::thread` and `std::function` support
- Move semantics for sockets and buffers
- Lambda-based completion handlers

### C++14

Support for C++14 is guarded by `__cpp_constexpr >= 201304L`. This adds relaxed `constexpr` support and additional overloads that leverage generic lambdas for more flexible asynchronous operations.

### C++17

When `__cpp_features >= 201803L` is available, Asio utilizes:
- `std::optional` and `std::any` for type-erased handlers
- Expanded `constexpr` capabilities
- Experimental coroutine support (when the compiler provides the Coroutines TS)

### C++20

Full coroutine support is unlocked when `__cpp_concepts >= 201907L` and `__cpp_coroutines >= 201902L` are detected. This enables:
- `co_await` for asynchronous operations
- `co_spawn` and `awaitable` types
- Concepts-based overloads
- `std::span`-aware APIs

### C++23 (Preview)

Experimental support for C++23 features is available when corresponding feature-test macros (such as `__cpp_expected`) are defined. This includes support for `std::expected` and further `constexpr` extensions.

## How Asio Detects Your Compiler's C++ Standard

Detection logic is centralized in [`include/asio/version.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/version.hpp). This header contains a series of `#if`/`#elif` blocks that define macros such as `ASIO_HAS_STD_CHRONO`, `ASIO_HAS_CO_AWAIT`, and `ASIO_HAS_STD_SPAN` based on the detected `__cplusplus` value and the presence of feature-test macros.

The library uses these macros throughout its codebase to conditionally enable or disable code paths. For example, [`include/asio/basic_waitable_timer.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/basic_waitable_timer.hpp) adapts its implementation to use `<chrono>` facilities only when `ASIO_HAS_STD_CHRONO` is defined.

## Practical Code Examples by Standard

### Using Asio with C++11 (Callback-Based)

On C++11 compilers, Asio uses traditional callback-based asynchronous operations:

```cpp
#include <asio.hpp>

asio::io_context ctx;
asio::ip::tcp::socket socket(ctx);
socket.async_connect(endpoint,
    [&](std::error_code ec) {
        if (!ec) { /* handle connection */ }
    });
ctx.run();

```

### Using Asio with C++20 (Coroutines)

With C++20 support, you can write asynchronous code using coroutines and the `use_awaitable` completion token:

```cpp
#include <asio.hpp>
#include <asio/co_spawn.hpp>
#include <asio/use_awaitable.hpp>

asio::awaitable<void> echo(asio::ip::tcp::socket sock) {
    std::array<char, 1024> data;
    std::size_t n = co_await sock.async_read_some(
        asio::buffer(data), asio::use_awaitable);
    co_await asio::async_write(sock,
        asio::buffer(data, n), asio::use_awaitable);
}

int main() {
    asio::io_context ctx;
    asio::co_spawn(ctx,
        []() -> asio::awaitable<void> {
            asio::ip::tcp::acceptor acceptor(
                co_await asio::this_coro::executor,
                {asio::ip::tcp::v4(), 12345});
            for (;;) {
                asio::ip::tcp::socket sock = co_await acceptor.async_accept(
                    asio::use_awaitable);
                asio::co_spawn(acceptor.get_executor(),
                               echo(std::move(sock)),
                               asio::detached);
            }
        },
        asio::detached);
    ctx.run();
}

```

### Conditional Compilation

You can check for specific features in your own code using Asio's feature macros:

```cpp
#if defined(ASIO_HAS_CO_AWAIT)
    // Coroutine-based API available
    co_await socket.async_read_some(buffer, asio::use_awaitable);
#else
    // Fallback to callback-based async functions
    socket.async_read_some(buffer, handler);
#endif

```

## Key Implementation Files

Several source files define how Asio adapts to different C++ standards:

- **[`include/asio/version.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/version.hpp)** – Central detection point for C++ standard levels and feature-test macros
- **[`include/asio/use_awaitable.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/use_awaitable.hpp)** – Provides the `use_awaitable` completion token for C++20 coroutines
- **[`include/asio/co_spawn.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/co_spawn.hpp)** – Helper for launching coroutines on an I/O executor (C++20)
- **[`include/asio/basic_waitable_timer.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/basic_waitable_timer.hpp)** – Timer implementation that adapts to available `<chrono>` facilities

## Summary

- Asio supports **C++03 through C++23**, with progressive feature enablement
- Standard detection occurs in [`include/asio/version.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/version.hpp) using `__cplusplus` and feature-test macros
- **C++11** brings `std::chrono`, lambdas, and move semantics
- **C++20** unlocks full coroutine support (`co_await`, `co_spawn`) and concepts
- Use `ASIO_HAS_CO_AWAIT` and similar macros for conditional compilation

## Frequently Asked Questions

### Does Asio require C++20 to use coroutines?

No, Asio provides coroutine support starting with C++17 when the compiler implements the Coroutines TS, but full standardized support requires C++20 with `__cpp_coroutines >= 201902L` detected. You can always use callback-based or futures-based APIs on older standards.

### How do I force Asio to use a specific C++ standard?

Asio automatically detects the standard from your compiler settings via `__cplusplus` and feature-test macros defined in [`include/asio/version.hpp`](https://github.com/chriskohlhoff/asio/blob/main/include/asio/version.hpp). Ensure you compile with the appropriate flag (e.g., `-std=c++20` for GCC/Clang or `/std:c++20` for MSVC) rather than defining internal Asio macros directly.

### Can I mix C++11 callback code with C++20 coroutines in the same project?

Yes, Asio's completion token model allows mixing styles. You can call `async_read_some` with a lambda in one part of your codebase and use `co_await` with `asio::use_awaitable` in another, provided you compile with C++20 or later for the coroutine portions.

### What happens if I compile Asio with C++03?

Core I/O functionality, timers, and sockets remain fully available. You simply lose access to `std::chrono` (using Boost.Chrono or custom time types instead), lambda handlers, and move semantics. The library falls back to classic implementation patterns automatically.