Trip report: February 2025 ISO C++ standards meeting (Hagenberg, Austria)
On Saturday, the ISO C++ committee completed the second-last design meeting of C++26, held in Hagenberg, Austria. There is just one meeting left before the C++26 feature set is finalized in June 2025 and draft C++26 is sent out for its international comment ballot (aka “Committee Draft” or “CD”), and C++26 is on track to … Continue reading Trip report: February 2025 ISO C++ standards meeting (Hagenberg, Austria) →
On Saturday, the ISO C++ committee completed the second-last design meeting of C++26, held in Hagenberg, Austria. There is just one meeting left before the C++26 feature set is finalized in June 2025 and draft C++26 is sent out for its international comment ballot (aka “Committee Draft” or “CD”), and C++26 is on track to be technically finalized two more meetings after that in early 2026.
This meeting was hosted by the University of Applied Sciences of Upper Austria, RISC Software GmbH, Softwarepark Hagenberg Upper Austria, Dynatrace, and Count It Group. Our hosts arranged for high-quality facilities at the University for our six-day meeting from Monday through Saturday. We had over 200 attendees, about two-thirds in-person and the others remote via Zoom, formally representing 31 nations. At each meeting we regularly have new guest attendees who have never attended before, and this time there were 36 new first-time guest attendees, mostly in-person, in addition to new attendees who are official national body representatives. To all of them, once again welcome!
The committee currently has 23 active subgroups, 13 of which met in 7 parallel tracks throughout the week. Some groups ran all week, and others ran for a few days or a part of a day, depending on their workloads. We also had combined informational evening sessions to inform the committee broadly about progress on one key topic this week: reflection wording review, and concurrent queues. You can find a brief summary of ISO procedures here.
Highlights
This time, the committee adopted the next set of features for C++26, and made significant progress on other features that are now expected to be complete in time for C+26.
In addition to features already approved for C++26 at previous meetings, at this meeting three major features made strong progress. In the core language:
- P2900 Contracts was adopted for C++26
- P2786 Trivial Relocatability was adopted for C++26
- P1967 #embed was adopted for C++26
In the standard library:
- P3471 Standard Library Hardening (which is also the first use of contracts) was adopted for C++26
- P0447 std::hive was adopted for C++26
Other noteworthy progress:
- P2996 Reflection is almost done its specification wording review aiming for C++26, and is expected to come up for vote for inclusion in C++26 at the June meeting
Language safety and software security improvements adopted for C++26
C++26 adopted two major features that improve language/library safety and software security: contracts, and a security-hardened standard library that has already delivered actual important security improvements just by recompiling/relinking existing C++ code (see references below).
Note: For definitions of “language safety” and “software security” and similar terms, see my 2024 essay “C++ safety, in context.”
C++26 Contracts
First, years in the making, we adopted P2900R14 “Contracts for C++” by Joshua Berne, Timur Doumler, and Andrzej Krzemieński, with Gašper Ažman, Peter Bindels, Louis Dionne, Tom Honermann, Lori Hughes, John Lakos, Lisa Lippincott, Jens Maurer, Ryan McDougall, Jason Merrill, Oliver J. Rosten, Iain Sandoe, and Ville Voutilainen. This is a huge paper (119 pages) that adds preconditions, postconditions, and contract_assert
(a major improvement that brings C’s “assert” macro into the language, with improvements). For an overview, see Timur Doumler’s blog post “Contracts for C++ explained in 5 minutes.” The main change last week is that the committee decided to postpone supporting contracts on virtual functions; work will continue on that and other extensions. Thanks to the coauthors, and to everyone in Study Group 21 (SG12) and the language evolution working group (EWG) and everyone who commented and gave feedback, for their hard work on this feature for many years!
Note: This is the second time contracts has been voted into draft standard C++. It was briefly part of draft C++20, but was then removed for further work.
Relatedly, P1494R4 “Partial program correctness” by Davis Herring adds the idea of “observable checkpoints” that limit the ability of undefined behavior to perform time-travel optimizations. This helps to eliminate some optimization pitfalls that range from not actually executing an enforced contract (see contracts, above) to security vulnerabilities. The paper also provides std::observable()
as a manual way of adding such a checkpoint in code.
C++26 hardened standard library
The second is another big step for language and library safety in C++26. Recall that:
- C++23 already eliminated returning a dangling reference to a local object at compile time (did you know that? try it now on Godbolt), which has already removed one common source of silent dangling.
- C++26 has already eliminated undefined behavior from uninitialized variables.
- And now in C++26…
… P3471R4 “Standard library hardening” by Konstantin Varlamov and Louis Dionne provides initial portable, cross-platform security guarantees for the C++ standard library too as part of C++26. It turns some common and frequently-exploited instances of undefined behavior in the C++ standard library into a contract violation (note: that makes it also the first user of the just-adopted contracts language feature, above! yes, WG21 does try to coordinate its delivered features).
In particular, only two (2) programming language weaknesses made the top 15 most dangerous software weaknesses in the MITRE 2024 CWE Top 25 Most Dangerous Software Weaknesses — and those two are Out-of-Bounds Write (#2) and Out-of-Bounds Read (#6).
This is why I keep repeating that, yes, we need to improve C (especially) and C++ memory safety, but that is far from the only thing we as an industry need to do. As we harden one area, attackers just shift to the next slowest animal in the herd. Already, above, we are seeing more and more of the MITRE Top 25 be not programming language memory safety issues… in 2024, it’s down to just 2 of the top 15. Sure we need to fix those 2 issues and others like them, but let’s never forget that we need to fix the other 13 of the top 15 too! For more on this, again please see my “C++ safety, in context” essay.
This continues to demonstrate what I’ve explained many times: Bounds safety is the lowest-hanging fruit in terms of things we need to address first. That’s why it’s a big deal that, as of Saturday, the C++26 hardened standard library focuses on bounds safety and requires that the all of following are guaranteed to be bounds-checked:
- In std::span: operator[], front, back, first, last, subspan, and constructors
- In the std::string_views: operator[], front, back, remove_prefix, remove_suffix
- In all sequence containers (e.g., std::vector, std::array): operator[], front, back, pop_front, pop_back
- In the std::strings: operator[], front, back, pop_back
- In the multidimensional std::mdspan: operator[], and constructors
- In std::bitset: operator[]
- In std::valarray: operator[]
- In std::optional: operator->, operator*
- In std::expected: operator->, operator*, error
And that’s just a start, that has already made a real impact on hardening production code including on popular platforms.
Importantly, user code gets this benefit just by building with a hardened C++26 standard library — without any code changes. If you’ve seen any of my recent talks, you know this is close to my heart… see especially
- this short clip in my code::dive 2024 talk about why C++26 removing undefined behavior for uninitialized locals is a model for adoptability and also
- this short clip in the Q&A about the societal value of improving C++.
I think that Konstantin and Louis express that value proposition beautifully in their paper’s Motivation section, and I’ll quote most of their appeal here (emphasis original)… they “get it”:
“There has been significantly increased attention to safety and security in C++ over the last few years, as exemplified by the well-known White House report and numerous recent security-related proposals.
“While it is important to explore ways to make new code safer, we believe that the highest priority to deliver immediate real-world value should be to make existing code safer with minimal or no effort on behalf of users. Indeed, the amount of existing security-critical C++ code is so large that rewriting it or modifying it is both economically unviable and dangerous given the risk of introducing new issues.
“There have been a few proposals accepted recently that eliminate some cases of undefined behavior in the core language. The standard library also contains many instances of undefined behavior, some of which is a direct source of security vulnerabilities; addressing those is often trivial, can be done with low overhead and almost no work on behalf of users.
“In fact, at the moment all three major library implementations have some notion of a hardened or debug mode. This clearly shows interest, both from users and from implementers, in having a safer mode for the standard library. However, we believe these efforts would be vastly more useful if they were standardized and provided portable, cross-platform guarantees to users; as it stands, implementations differ in levels of coverage, performance guarantees and ways to enable the safer mode.
“Finally, leaving security of the library to be a pure vendor extension fails to position ISO C++ as providing a credible solution for code bases with formal security requirements. We believe that formally requiring the basic safety guarantees that most implementations already provide in one way or another could make a significant difference from the point of view of anyone writing or following safety and security coding standards and guidelines.”
In the next section, they demonstrate that this isn’t some theoretical improvement — it’s an improvement that is standardizing what is already shipping and significantly hardening existing C++ code today (emphasis added):
“All three major implementations provide vendor-specific ways of enabling library assertions as proposed in this paper, today.
- We have experience deploying hardening on Apple platforms in several existing codebases.
- Google recently published an article where they describe their experience with deploying this very technology to hundreds of millions of lines of code. They reported a performance impact as low as 0.3% and finding over 1000 bugs, including security-critical ones.
- Google Andromeda published an article ~1 year ago about their successful experience enabling hardening.
- The libc++ maintainers have received numerous informal reports of hardening being turned on and helping find bugs in codebases.
Overall, standard library hardening has been a huge success, in fact we never expected so much success. The reception has been overwhelmingly positive and while the quality of implementation will never be perfect, we are working hard to expand the scope of hardening in libc++, to improve its performance and the user experience.
This further demonstrates that not only is C++ making serious progress to improve, but that many of the language safety and software security improvements are already shipping without waiting for standardization. Standardization is still important, of course, because it makes these improvements available portably, with portable guarantees for C++ code on all platforms.
More things adopted for C++26: Core language changes/features
Note: These links are to the most recent public version of each paper. If a paper was tweaked at the meeting before being approved, the link tracks and will automatically find the updated version as soon as it’s uploaded to the public site.
In addition to fixing a list of defect reports, the core language adopted 8 papers, including contracts (above) and the following…
P2786R13 “Trivial relocatability for C++26” by Alisdair Meredith, Mungo Gill, Joshua Berne, Corentin Jabot, Pablo Halpern, and Lori Hughes adds stronger support for optimizing the copying of memcpy-able types in the C++ language. This removes a source of “undefined behavior” that many container libraries rely on because it happens to be useful and probably-benign, and not only guarantees it is well-defined but also makes the optimizations more widely available for more types. Thank you, Alisdair and your collaborators, and thanks also to the authors of other trivial-relocation proposals that were not adopted! All of the input has made the result better, and we appreciate all the continued feedback.
P1967R14 “#embed – a scannable, tooling-friendly binary resource inclusion mechanism” by JeanHeyd Meneide enables “#include for binary data” — a portable way to pull binary data into a program without external tools and build system support. The introduction is clear and crisp:
“For well over 40 years, people have been trying to plant data into executables for varying reasons. Whether it is to provide a base image with which to flash hardware in a hard reset, icons that get packaged with an application, or scripts that are intrinsically tied to the program at compilation time, there has always been a strong need to couple and ship binary data with an application.
“Neither C nor C++ makes this easy for users to do, resulting in many individuals reaching for utilities such as xxd, writing python scripts, or engaging in highly platform-specific linker calls to set up extern variables pointing at their data. Each of these approaches come with benefits and drawbacks. For example, while working with the linker directly allows injection of very large amounts of data (5 MB and upwards), it does not allow accessing that data at any other point except runtime. Conversely, doing all of these things portably across systems and additionally maintaining the dependencies of all these resources and files in build systems both like and unlike make is a tedious task.
“Thusly, we propose a new preprocessor directive whose sole purpose is to be #include, but for binary data: #embed.”
Note that this feature has already been approved for inclusion in the next revision of C as well. See the proposal paper, especially sections 3.3 and 4.1, for more delightful background and design alternative discussion.
P2841R7 “Concept and variable-template template-parameters” by Corentin Jabot, Gašper Ažman, James Touton, and Hubert Tong adds the ability of passing concepts and variable templates as template parameters. Thank you, Corentin and your coauthors!
More things adopted for C++26: Standard library changes/features
In addition to fixing a list of defect reports, the standard library adopted 15 papers, including the following…
P0447R28 “Introduction of std::hive to the standard library” by Matthew Bentley is a major library addition that formalizes a widely-used high-performance data structure. From the paper’s overview:
“Hive is a formalisation, extension and optimization of what is typically known as a ‘bucket array’ or ‘object pool’ container in game programming circles. Thanks to all the people who’ve come forward in support of the paper over the years, I know that similar structures exist in various incarnations across many fields including high-performance computing, high performance trading, 3D simulation, physics simulation, robotics, server/client application and particle simulation fields (see this google groups discussion, the hive supporting paper #1 and appendix links to prior art).
“The concept of a bucket array is: you have multiple memory blocks of elements, and a boolean token for each element which denotes whether or not that element is ‘active’ or ‘erased’ – commonly known as a skipfield. If it is ‘erased’, it is skipped over during iteration. When all elements in a block are erased, the block is removed, so that iteration does not lose performance by having to skip empty blocks. If an insertion occurs when all the blocks are full, a new memory block is allocated.
“The advantages of this structure are as follows: because a skipfield is used, no reallocation of elements is necessary upon erasure. Because the structure uses multiple memory blocks, insertions to a full container also do not trigger reallocations. This means that element memory locations stay stable and iterators stay valid regardless of erasure/insertion. This is highly desirable, for example, in game programming because there are usually multiple elements in different containers which need to reference each other during gameplay, and elements are being inserted or erased in real time. The only non-associative standard library container which also has this feature is std::list, but it is undesirable for performance and memory-usage reasons. This does not stop it being used in many open-source projects due to this feature and its splice operations.
“Problematic aspects of a typical bucket array are that they tend to have a fixed memory block size, tend to not re-use memory locations from erased elements, and utilize a boolean skipfield. The fixed block size (as opposed to block sizes with a growth factor) and lack of erased-element re-use leads to far more allocations/deallocations than is necessary, and creates memory waste when memory blocks have many erased elements but are not entirely empty. Given that allocation is a costly operation in most operating systems, this becomes important in performance-critical environments. The boolean skipfield makes iteration time complexity at worst O(n) in capacity(), as there is no way of knowing ahead of time how many erased elements occur between any two non-erased elements. This can create variable latency during iteration. It also requires branching code for each skipfield node, which may cause performance issues on processors with deep pipelines and poor branch-prediction failure performance.
“A hive uses a non-boolean method for skipping erased elements, which allows for more-predictable iteration performance than a bucket array and O(1) iteration time complexity; the latter of which means it meets the C++ standard requirements for iterators, which a boolean method doesn’t. It has an (optional – on by default) growth factor for memory blocks and reuses erased element locations upon insertion, which leads to fewer allocations/reallocations. Because it reuses erased element memory space, the exact location of insertion is undefined. Insertion is therefore considered unordered, but the container is sortable. Lastly, because there is no way of predicting in advance where erasures (‘skips’) may occur between non-erased elements, an O(1) time complexity [ ] operator is not possible and thereby the container is bidirectional but not random-access.”
Continuing the “making more things constexpr (and consteval)” drumbeat that allows more and more of the full C++ language and standard library be usable in constexpr code, we approved a set of constexpr extensions:
- P3372R3 “constexpr containers and adaptors” by Hana Dusíková makes all containers and adapters constexpr (except for the new std::hive, above).
- P3378R2 “constexpr exception types” by Hana Dusíková makes all exception types used with constexpr code be constexpr too.
Thanks, Hana! These are just the latest of a continued stream of Hana’s papers for constexpr-ing the C++ world; much appreciated — děkuju and arigato!
You may recall that at our last meeting we merged std::simd by Matthias Kretz for high-throughput parallel/vector programming into draft C++26. On Saturday we approved a set of further extensions and refinements, including:
- P3441R2 “Rename simd_split to simd_chunk” by Daniel Towner and Ruslan Arutyunyan not only does what it says on the tin, but also adds new convenience overloads.
- P2663R7 “Interleaved complex values support in std::simd” by Daniel Towner and Ruslan Arutyunyan adds interleaved complex values support.
- P2933R4 “Extend
header function with overloads for std::simd” by (you guessed it!) Daniel Towner and Ruslan Arutyunyan.
Not to be outdone, P2976R1 “Freestanding library: algorithm, numeric, and random” by Ben Craig continues Ben’s march toward making a huge amount of C++ available on freestanding implementations. Thanks, Ben!
Last but not least, P3019R14 “indirect and polymorphic: Vocabulary types for composite class design” by Jonathan Coe, Antony Peacock, and Sean Parent adds value-semantic types for polymorphic objects to the standard library. This makes polymorphic types much easier to treat as values in value-like algorithms and use cases. Thanks very much, Jonathan and Antony and Sean!
What’s next
Thank you to all the experts who worked all week in all the subgroups to achieve so much this week!
Our next meeting will be this June in Sofia, Bulgaria hosted by Chaos Group and C++ Alliance.
Thank you again to the over 200 experts who attended on-site and on-line at this week’s meeting, and the many more who participate in standardization through their national bodies!
But we’re not slowing down… in case you think C++“26” sounds very far away, it sure isn’t… we’re only one meeting away before the C++26 freeze in June, and even before that compilers are already aggressively implementing C++26, with GCC and Clang having already implemented about two-thirds of C++26’s language features adopted so far! C++ is a living language and moving fast. Thank you again to everyone reading this for your interest and support for C++ and its standardization.