C++26 is final: reflection, contracts, and the std::simd everyone argues about
The ISO C++ committee closed C++26 at the Croydon meeting in March 2026, and by the third week of July the reaction had sorted itself into three piles. Static reflection gets the applause, contracts and the sender/receiver async model get a careful nod, and std::simd gets the fight. I write NEON kernels for local inference on Apple Silicon, so the fight is the part I have to take a position on.
What is actually in the standard
- Static compile-time reflection. Herb Sutter and Hana Dusíková have both described it as something close to a new language. For a C++23 codebase full of registration macros, this is the feature that deletes code.
- Contracts. Preconditions and postconditions in the language rather than in a macro header.
- Sender/receiver. The standard async model, finally.
- std::simd (P1928). A library-based portable SIMD type lifted from Parallelism TS 2. Write the loop once, compile for AVX2, AVX-512, NEON or SVE.
Tooling is moving already: GCC patches for std::simd are on the mailing list (Phoronix covered them), and CLion 2026.2 shipped in July with C++26 reflection support.
Why std::simd draws fire
The loudest critique, summarised in a piece titled "A SIMD library nobody asked for", is that this is a 2012 solution arriving late. The specific complaints are testable, which is why they are worth listing:
- Slower compilation, on kernel files that are already template-heavy.
- A bad default vector width. The abstraction chooses for you, and on hardware where the right width depends on the data type and the loop shape, a wrong default costs real throughput.
- Missing expressiveness. Critics say the operations that matter in real SIMD work, the shuffles, lane permutes and masked gathers, are hard or impossible to write through the portable type.
- Autovectorization plus ISPC or Google Highway already solve the practical problem, with a decade of production mileage.
The critics are right about the timing and partially right about the ergonomics. Where I disagree is the implied conclusion that a standard type is therefore useless. It is a lowest common denominator, and a lot of inference code is exactly that.
A portable SIMD type is a promise about the source, not about the codegen; the only thing that settles the argument is a benchmark on your own kernel.
What it means for inference kernels
Most of the hot loops in a local inference stack are boring: dot products for matmul tiles, dequantization of 4-bit and 8-bit weights, softmax, RoPE rotation, RMSNorm. Those are the loops where std::simd should be fine, because they are dense, aligned and regular. Today I keep a NEON copy and an AVX2 copy of several of them under an ifdef, and the drift between them is a real maintenance cost.
The loops where I expect std::simd to leave performance on the table are the irregular ones: the table lookups inside 4-bit dequant, anything with gathers, the tail handling at the end of a row. That is where the abstraction sometimes cannot express the access pattern that makes the kernel fast, so measure against hand intrinsics before you trust it. If you run models through MLX or Metal you are not writing these loops, but the same trade-off decides which framework wins at which model size.
A benchmark plan before you migrate anything
- Pick three kernels: one dense (dot product), one irregular (4-bit dequant), one with tails (softmax over odd lengths).
- Build each three ways: current intrinsics, std::simd on a GCC build with the patches, and Highway.
- Measure tokens per second on a real model, not microbenchmark GFLOPS, on both an M-series machine and an x86 box.
- Record compile time per translation unit. If it doubles, that is a cost your CI pays daily.
- Keep the intrinsics version until the portable version is within a few percent on every one of the three.
The honest gap
I have no numbers of my own yet, and neither does most of the criticism. "Slow compile" and "bad default width" are claims from commentary, not from a published measurement on a shipping compiler. The GCC patches are patches, not a release, and Clang and MSVC will each have their own story. Until there is a compiler you can actually run against a real kernel, the fair verdict on std::simd is unmeasured, which is a different thing from bad.