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

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.

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. 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 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:

#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:

#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:

#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:

Summary

  • Asio supports C++03 through C++23, with progressive feature enablement
  • Standard detection occurs in 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →