Skip to content
C++
C++26
In progress — expected 2026
Draft

C++26

The next major C++ standard, currently in final balloting. Static reflection transforms metaprogramming. Contracts bring Design by Contract to the language. std::execution finally lands the async story C++ has needed for a decade.

Static reflection
Contracts
std::execution
std::simd
#embed
std::inplace_vector
Format ranges

Core Language

Static reflection (P2996)

Query and manipulate type information at compile time. Generate serializers, loggers, and boilerplate from struct definitions automatically.

#include <meta>

struct Point { int x, y; };

// Reflect on struct members
consteval std::string_view name_of(std::meta::info r) {
    return std::meta::name_of(r);
}

// Generate toString() for any struct
template<typename T>
std::string to_string(const T& obj) {
    std::string result = "{";
    bool first = true;
    [:std::meta::members_of(^T):] >> [&]<auto M>() {
        if (!first) result += ", ";
        result += std::string(std::meta::name_of(M));
        result += ": ";
        result += std::to_string(obj.[:M:]);
        first = false;
    };
    return result + "}";
}

// to_string(Point{1, 2}) == "{x: 1, y: 2}"
Contracts (pre/post/assert)

First-class language support for Design by Contract. [[pre:]], [[post:]], and contract_assert() with configurable violation handlers.

// Precondition — checked on entry
int sqrt_int(int n)
    [[pre: n >= 0]]
    [[post r: r >= 0]]
{
    return static_cast<int>(std::sqrt(n));
}

// Assert — checked at point of use
void process(std::vector<int>& v, std::size_t i) {
    [[assert: i < v.size()]];
    v[i] *= 2;
}

// Violation handler (set globally)
// violation → calls the registered handler (default: std::terminate)
Pack indexing (P2662)

Direct index into variadic parameter packs with pack...[N]. Eliminates recursive template metaprogramming for element access.

template<typename... Ts>
using first_t = Ts...[0];   // type indexing

template<typename... Ts>
auto get_first(Ts... args) {
    return args...[0];        // value indexing
}

template<std::size_t I, typename... Ts>
auto get(Ts... args) {
    return args...[I];        // runtime-index (I must be constexpr)
}

first_t<int, double, char>  x = 42;  // int
auto val = get<2>(10, 20.0, 'a');    // 'a'
#embed — binary resource inclusion

Include binary files (images, shaders, certificates) directly as data arrays. Replaces xxd-generated headers.

// icon.png included as a byte sequence
constexpr std::uint8_t icon_data[] = {
    #embed "icon.png"
};

// With limit — first 4 bytes only
constexpr std::uint8_t header[] = {
    #embed "file.bin" limit(4)
};

// Is the resource non-empty?
#if __has_embed("resource.bin")
// ...
#endif

Library

std::execution — Senders/Receivers (P2300)

A unified model for async work: structured concurrency, cancellation, and scheduler abstraction. The async/await that C++ deserves.

#include <execution>

namespace ex = std::execution;

// Describe async work as a pipeline of senders
auto work = ex::just(42)
    | ex::then([](int n) { return n * 2; })
    | ex::then([](int n) { return std::to_string(n); });

// Schedule on a thread pool
ex::thread_pool pool{4};
auto result = ex::sync_wait(
    ex::on(pool.get_scheduler(), std::move(work))
);
// result == "84"
std::simd — portable SIMD (P1928)

First-class portable SIMD types that map to hardware (SSE, AVX, NEON). Write vectorized code once, run everywhere.

#include <simd>

namespace stdx = std::experimental;

// Process 4 floats at once (maps to SSE/NEON)
void scale(std::span<float> data, float factor) {
    using V = stdx::native_simd<float>;
    std::size_t i = 0;

    for (; i + V::size() <= data.size(); i += V::size()) {
        V v{data.data() + i, stdx::element_aligned};
        v *= factor;
        v.copy_to(data.data() + i, stdx::element_aligned);
    }
    for (; i < data.size(); ++i)
        data[i] *= factor;  // scalar tail
}
std::inplace_vector<T, N>

A vector with compile-time capacity cap stored on the stack. No heap allocation, no dynamic capacity. The std version of boost::static_vector.

#include <inplace_vector>

// Stack-allocated vector with max 8 elements
std::inplace_vector<int, 8> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);

// Has vector-like API
std::ranges::sort(v);
// No heap, no allocator, fits in stack frame
Formatting improvements

std::format gains support for formatting ranges, tuples, and pairs. Write {v} to format a vector directly.

#include <format>
#include <vector>
#include <map>

std::vector<int> v{1, 2, 3, 4};
std::println("{}", v);         // [1, 2, 3, 4]
std::println("{:n}", v);       // 1, 2, 3, 4  (no brackets)

std::map<std::string, int> m{{"a", 1}, {"b", 2}};
std::println("{}", m);         // {"a": 1, "b": 2}

std::tuple<int, double, std::string> t{1, 2.5, "hi"};
std::println("{}", t);         // (1, 2.5, hi)
C++23C++29 (future)