In summary: In a historic vote that closed on October 22, 2026, the draft standard saw C++26 rejected by ISO national standards bodies. At the heart of the controversy: the inclusion of contracts (P2900), strongly contested by Bjarne Stroustrup and several compiler vendors on grounds of safety and maturity. This rejection puts pressure on the C++26 release schedule and raises questions about retaining flagship features such as static reflection.
The evolution of the C++ language is experiencing an unprecedented crisis. While the publication of the upcoming standard seemed on track, the decision of national committees has disrupted the ISO standard roadmap. Our Software Engineering teams review in detail the reasons that led to C++26 being rejected, the technical disagreements surrounding contract programming, and the potential scenarios to resolve the crisis.
The C++26 Draft Rejected by National Bodies
For the first time in the history of C++, national standards bodies have rejected the final draft of a standard. The cause: contracts, the major new feature of C++26 intended to offer a language-level solution to contract programming and permanently bury the C-inherited assert macro. The vote, closed on October 22, 2026, garnered 13 votes in favor, 9 against, and 12 abstentions. This is far from the two-thirds approval and the maximum of one-quarter negative votes required by ISO.
1. Contracts, a Longstanding Ambition for C++
Contracts allow conditions that a function expects and guarantees to be written directly in code. The adopted proposal (P2900) offers three forms: a pre/post pair, representing respectively a function’s preconditions and postconditions, placed at its declaration, and a contract_assert assertion in its body.
int sqrt(int x)
pre (x >= 0)
post (r : r >= 0);
Each contract can be ignored, observed (the violation is reported, execution continues), or enforced (the program terminates). This choice is not made in code but at compile-time, typically via a compiler flag. A global violation handler, replaceable by the application, centralizes error handling.
The idea is to expose contracts to the caller, who can check them if needed, while analysis tools can access them without inspecting a function’s implementation. Historically, these contracts were documented in comments—for instance in Doxygen format /// @pre \p x >= 0—and then added to function bodies, potentially with assert, which introduced a risk of divergence over time between comments and code.
Moreover, contracts offer a ready-made solution for STL hardening, for example by adding pre(index < size()) to std::vector::operator[].
This idea is not new to C++: an initial proposal dates back to 2004, and a version of contracts had already been adopted for C++20 before being pulled at the last minute in 2019. The committee started from scratch with a “minimum viable product” intended to be completed later. This version was adopted in February 2025 by 100 votes to 14 by the committee.
2. Technical and Procedural Disagreement
A minority within the committee, notably centered around Bjarne Stroustrup and the compiler implementation teams from Microsoft and EDG, never accepted this design. Having failed to prevail within the committee, they addressed national bodies directly. Several of them, including AFNOR for France, had in fact requested the removal of contracts as early as 2025. Three main concerns dominate.
2.1 No Guarantees, and a Frozen Default
Nothing in C++26 can guarantee the inviolability of a contract from code. Only compilation flags can control their activation level; a contract therefore cannot be enforced from the source code itself. Furthermore, their activation level lacks granularity: either all are activated, or all are disabled. One cannot define mandatory contracts alongside contracts verified only in debug mode, for example.
Worse, an inline function compiled with different settings across two libraries can lose its check during the link phase without anyone knowing.
Labels, planned for C++29 (P3400), would address part of these points by adding a pre syntax, where label allows for a dedicated strategy. Except this would only apply to those who use them: the short syntax, without a label, would retain its current behavior, as it cannot be changed without breaking existing code.
Proponents respond that the same problems already exist with assert, where it even constitutes undefined behavior, and that an unexecuted check is “no worse than no assertion at all.” This raises concerns because, when adding a feature to C++, the goal should be to learn from historical solutions and avoid repeating their shortcomings.
2.2 Insufficient Maturity
Contracts are implemented in GCC and Clang, but deployment experience has been limited to contract_assert. Preconditions and postconditions on declarations—the true novelty—have not been tested at scale.
This argument is put forward by some contract opponents, but not all. It must be recognized that a lack of maturity is also a shortcoming of static reflection and std::execution, which were nonetheless also adopted into the standard.
2.3 Contested Consensus
Here we enter procedural territory. When all goes well, a proposal advances through various votes and polls. Committee members vote SF (strongly in favor), F (in favor), N (neutral), A (against), or SA (strongly against). If a member votes A or SA, they must accompany their vote with a comment or question justifying their rejection. Subsequently, it is customary (though not mandatory) for proposal authors to address questions to clear up doubts or rectify an identified flaw.
Opponents argue that the design moved forward through votes while rarely addressing their objections. The former chair of the study group, John Spicer, even published a mea culpa acknowledging that he supported a pace that sidelined objections from key members, including compiler implementers from Microsoft and EDG. But contract proponents point out that every objection was debated across multiple meetings, and that opposition, however persistent, is not a veto power. In reality, the prevailing feeling is that debates did not provide solutions to the objections, but rather attempted to downplay them.
The debate does not fall strictly along party lines. Andrzej Krzemieński, co-author of the proposal, admits that his model “is not adopted by a significant part” of the committee, and considers it “surprising” that opposition from two compiler vendors was not enough to disqualify it.
3. C++26 Rejected: What Next for the Standard?
The decision does not rest with the C++ committee itself. The chair of the relevant ISO subcommittee (SC22) will decide, based on the committee’s recommendation expected at its meeting in Búzios (Brazil) in November. ISO rules offer four paths: a revised standard submitted to a new eight-week vote, a return to the committee draft stage (for a new vote after substantial revisions), publication as a Technical Specification (C++26 would no longer be an official language standard, but an implementation possibility), or abandonment. Failing approval by the end of 2027, the project will be automatically canceled.
Proponents propose holding a new vote without modifying contracts, relying on the committee’s official responses to change the minds of opposing countries (since National Body rejections are also accompanied by comments and questions).
Yet this is a difficult bet: even if all 12 abstaining countries voted “Yes”, the 9 negative votes would still represent more than 25%. In addition to convincing all abstaining nations, at least 4 countries would need to switch sides.
The alternative path is to remove contracts in order to ship the rest of C++26, most notably the highly anticipated static reflection and std::execution. Removal is not trivial: several parts of the standard must be rewritten and submitted again to national bodies. Standard library hardening will also need to be decoupled from contracts. While widely deployed (notably by Google, which caught over a thousand bugs for a 0.3% overhead), it could be preserved because its initial version was specified without contracts, and existing implementations are already decoupled from them.
There is precedent for dropping features under threat of definitive rejection. In 2008, a proposal to add concepts was removed from C++0x (the future C++11). They returned, better designed, in C++20. That removal, however, took place prior to the first National Body vote.
Conclusion
Beyond contracts, this vote raises a question of governance. For some, it proves that the external oversight provided by ISO works when a committee overrides serious opposition. For others, it sets a dangerous precedent: a committee majority can be blocked by a minority holding leverage within National Bodies. The Búzios meeting will reveal whether the committee chooses compromise—saving C++26 without contracts—or a showdown. In either case, the lesson holds for the future: explaining why an objection is overridden matters just as much as counting votes.
What Future for the C++26 Standard?
The rejection of C++26 by national bodies marks a historic turning point in the language’s evolution. Far from an outright abandonment, this vote penalizes rushing through a major feature—contracts (P2900)—technically contested by key figures such as Bjarne Stroustrup and compiler implementers.
The immediate focus shifts to the Búzios meeting and the SC22 decision: the most pragmatic scenario remains dropping contracts to secure the timely publication of other highly anticipated features, particularly static reflection and std::execution.
Why was the C++26 standard rejected by ISO?
The final draft of the C++26 standard was rejected by national standards bodies (13 votes in favor, 9 against, 12 abstentions, falling short of the required two-thirds threshold) due to the controversial inclusion of contracts (proposal P2900). An influential minority, led notably by language creator Bjarne Stroustrup and compiler teams from Microsoft and EDG, argues there is a lack of runtime guarantees, insufficient granularity, and inadequate technical maturity.
Does seeing C++26 rejected permanently cancel the standard?
No. Having the C++26 draft rejected in this ballot does not mean the project is abandoned. The chair of the ISO subcommittee (SC22) must decide following the Búzios meeting. Four outcomes remain possible:
- A swift revision submitted to a new 8-week ballot;
- A return to the committee draft stage for more substantial rework;
- Publication as a Technical Specification (Technical Specification) without official standard status;
- The outright removal of contracts to publish the rest of the standard on schedule.
What happens to other new features like static reflection and std::execution?
Highly anticipated features like static reflection and the std::execution parallelism library are not fundamentally questioned. If the committee decides to remove contracts to unblock C++26 approval, these additions can be published in the revised standard, provided the editorial decoupling work is completed in time.
What are contracts in C++ and what is the issue?
Contracts introduce native syntax for preconditions (pre), postconditions (post), and assertions (contract_assert) to replace the legacy assert macro. Criticisms focus on the fact that their activation depends entirely on compiler options without any way to enforce a mandatory contract in code, along with risks of losing checks during the linking phase between differently compiled libraries.
Consult Reference Documents and Sources (ISO Proposals, Critiques, and Debates)
The Proposal
- P2900R14, Contracts for C++: the adopted specification
- P2899R1, Contracts for C++ — Rationale: full rationale and history
- P3471R4, Standard library hardening
The Critiques
- P3573R0, Contract concerns (Stroustrup, Dos Reis, Vandevoorde, Spicer et al.)
- P3829R0, Contracts do not belong in the language
- P3835R0, Contracts make C++ less safe — full stop!: mixed mode
- P3853R0, A thesis+antithesis=synthesis rumination on Contracts: the risk of freezing default behavior
- P4238R1, Returning C++26 for the Evaluation It Skipped: the procedural argument
- P4381R0, Chairing SG21 and then objecting to Contracts (John Spicer’s mea culpa)
The Defenses
- P3846R1, C++26 Contract Assertions, Reasserted: point-by-point response to objections
- P4433R0, Do not remove Contracts from C++26
- P4388R0, Ship C++26
- P3850R1, A proposed plan for extending Contracts in C++29
- P3400R5, Controlling Contract-Assertion Properties: labels
In Between
- P4020R0, Concerns about contract assertions (Krzemieński, co-author of P2900)