The C++ Standard Cycle - From C++23 to C++26
A standard every three years
The C++ standards committee, ISO/IEC JTC1/SC22/WG21, adopted a fixed three-year cycle after the long gap between C++03 and C++11. The pattern since:
| Standard | Published | Character |
|---|---|---|
| C++11 | 2011 | The large one: move semantics, lambdas, auto, threading |
| C++14 | 2014 | Small, corrective |
| C++17 | 2017 | Medium: structured bindings, std::optional, filesystem, parallel algorithms |
| C++20 | 2020 | Large: concepts, ranges, coroutines, modules |
| C++23 | 2023 | Medium: std::expected, std::mdspan, std::print, deducing this |
| C++26 | Expected 2026 | In progress |
The rhythm has been roughly alternating: a large standard, then a consolidating one. C++20 was large and C++23 comparatively modest; C++26 is expected to be substantial again.
How a feature reaches the standard
Proposals progress through study groups, then the language or library evolution working groups, then core or library wording review, before a plenary vote adopts them into the working draft. Features must be in the draft by a published feature-freeze date to appear in that cycle.
Unlike some standards bodies, WG21 does not require shipping implementations before adoption, though implementation experience carries substantial weight. This is part of why compiler support can lag - some features are standardised before any compiler has fully implemented them.
C++23 in practice
C++23 was a consolidation release, and its most useful additions are small:
#include <print>
#include <expected>
std::expected<int, std::string> parse(std::string_view s);
int main() {
if (auto r = parse("42")) {
std::print("value: {}\n", *r);
} else {
std::print("error: {}\n", r.error());
}
}
std::print finally provides formatted output without iostreams or a third-party library.
std::expected gives a standard vocabulary type for operations that can fail without exceptions.
std::mdspan provides multidimensional array views, and deducing this removes a long-standing source of
duplicated const and reference overloads.
What C++26 is expected to bring
The headline items under discussion for C++26 have included:
- Reflection, giving compile-time introspection of types - long requested and the most significant of the candidates.
- Contracts, for expressing preconditions and postconditions in the language.
std::execution, a standard framework for asynchronous and parallel execution.- Safety-related work, including erroneous behaviour for uninitialised reads, which narrows one class of undefined behaviour.
- Standard library hardening, giving implementations a defined mode with bounds checking.
As always, what is in the working draft ahead of publication and what is in the final standard can differ, and features are removed late in the cycle when problems surface.
Compiler support is the real constraint
The gap between a standard being published and being usable is where most teams live. GCC, Clang and MSVC implement features at different rates, and the standard library implementations - libstdc++, libc++ and the MSVC STL - lag separately from the compiler frontends.
Modules are the clearest example: standardised in C++20, they remain unevenly supported and awkwardly integrated with build systems years later.
Practical approach:
- Check feature-test macros rather than the standard version.
__cpp_lib_expectedtells you whether the library feature exists;-std=c++23does not. - Consult support matrices for your specific compiler versions before committing to a feature.
- Set the standard version to what your oldest supported toolchain handles, not to the newest published.
#if __cpp_lib_expected >= 202202L
// use std::expected
#else
// fall back
#endif
Choosing a baseline
For most projects in 2026, C++17 remains the safest broad baseline and C++20 is realistic where you control the toolchain. C++23 is adoptable in parts - the library additions are widely available even where language features are not. C++26 is a planning horizon rather than something to build on today.
Conclusion
C++ publishes a standard every three years, alternating between large and consolidating releases. The standard’s publication date is the beginning of availability, not the end: compiler and library support determine what you can actually use, and they arrive separately and unevenly. Track feature-test macros rather than standard versions, and pick a baseline from your toolchain rather than from the calendar.