
C++26 is adding one of the more debated features in recent language development: contracts. The idea itself is not new, but its formal inclusion in the standard has brought an old disagreement back into focus. At stake is a familiar question in systems programming: how much should the language enforce correctness, and how much should be left to the developer?
Before the debate makes sense, the concept itself needs to be clear.
What a C++ contract actually is
A contract in C++ is a way to express assumptions directly in code. It allows a function to state what must be true before it runs, what it guarantees after it finishes, or what conditions must remain valid while it executes.
In practice, these are constraints on usage and behavior. A function might require that a value is within a certain range or that an object is in a valid state before proceeding. Instead of leaving these assumptions in comments or scattered checks, contracts bring them into a form that tools and compilers can recognize.
Unlike traditional assertions, contracts are not tied to a single enforcement model. They can be ignored, checked, or enforced depending on how the program is built. That flexibility is not an implementation detail; it is part of the design.
How they look in code
A simple precondition example:
int divide(int a, int b)
[[expects: b != 0]]
{
return a / b;
}
This states that b must not be zero. If the condition fails, the behavior depends on the contract mode selected at compile or runtime.
A postcondition example:
int increment(int x)
[[ensures: return_value == x + 1]]
{
return x + 1;
}
This expresses a guarantee about the return value after execution completes.
These are not runtime assertions in the traditional sense. They are designed to be configurable. Depending on the build configuration, they may be ignored, checked, or enforced strictly.
Who defines C++ contracts
C++ is standardized through ISO, under the committee known as WG21. This group includes compiler vendors, large tech companies, and independent experts. No single organization controls the language, and no company can unilaterally introduce features into the standard.
Contracts are the result of this collective process. They reflect compromise rather than a single design vision, which helps explain why they look the way they do.
Why contracts took so long
The idea has been circulating for decades. Early discussions go back to the period around C++11 and C++14, when the community started looking for ways to make assumptions in code more explicit and machine-checkable.
The motivation was straightforward. Large C++ systems already rely on implicit expectations about data validity, object state, and function inputs. These expectations are often left informal, which makes them hard to verify and easy to break.
Turning those assumptions into something the language understands sounded simple in principle. In practice, it was not. Every major proposal ran into disagreement over what should happen when a contract is violated. Some designs treated violations as runtime errors. Others tried to tie them into compiler optimization. Some proposals went further and blurred the line between contract failure and undefined behavior.
None of these approaches managed to settle consensus for long. The result is that contracts remained in discussion for years without becoming part of the standard.
C++26 reflects a compromise that avoids forcing a single strict model.
Why the debate is still active
Most developers do not disagree that contracts are useful. Making assumptions explicit is almost always an improvement over leaving them implicit.
The disagreement starts when expectations go further than that.
Critics argue that contracts do not address the deeper structural issues in C++. Memory safety problems, undefined behavior, and pointer misuse remain untouched. From this perspective, contracts improve readability and debugging, but not safety in any fundamental sense.
This argument often comes with comparisons to Rust. In Rust, the compiler enforces memory safety rules at compile time through ownership and borrowing. Certain classes of bugs common in C++ simply do not compile.
From that angle, contracts look incremental rather than transformative.
Supporters see the situation differently. C++ is not a new language in search of an ideal design. It is a long-established ecosystem embedded in critical systems that cannot realistically be rewritten. In that environment, incremental improvements are not a compromise but a necessity.
Contracts, in this view, are valuable because they make existing codebases more explicit and less error-prone without disrupting them.
The deeper split
The disagreement around contracts reflects a broader divide in systems programming.
One side expects the language to enforce correctness as much as possible, even if that limits flexibility. The other side treats flexibility and control as non-negotiable, even if it requires more discipline from the developer.
C++ has always leaned toward the second approach. Contracts do not change that direction. They simply add structure inside it.
Why timing matters
The arrival of contracts in C++26 comes at a time when software reliability and memory safety are under increasing scrutiny. High-impact vulnerabilities have pushed organizations and governments to rethink how low-level software is written.
At the same time, rewriting existing C++ systems is rarely realistic. Many of them are deeply embedded in infrastructure that has evolved over decades.
C++26 follows the path of gradual change rather than replacement. Contracts sit alongside other ongoing improvements aimed at making code safer without breaking compatibility or performance expectations.
What contracts will actually change
Contracts will not eliminate undefined behavior, nor will they turn C++ into a memory-safe language. Their impact is more practical and limited.
They make assumptions explicit. They give tools more information to work with. They help surface certain classes of errors earlier in development. In large codebases, that alone can be significant.
How useful they become depends less on the feature itself and more on how consistently it is adopted and enforced in real projects.
Conclusion
C++26 contracts are not a turning point in the language’s philosophy. They are an attempt to formalize something developers have been doing informally for years.
The reaction to them reflects a long-running tension in C++ between control and safety, between evolution and redesign.
Nothing about that tension is new. Contracts simply make it more visible.
References
ISO C++ Standard Committee (WG21) overview and papers on contracts proposal and evolution
https://isocpp.org/std/the-committee
https://www.open-std.org/jtc1/sc22/wg21
C++ contracts proposal background and design discussions (WG21 papers archive)
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023
C++ language standard draft information (C++26 direction and features tracking)
https://en.cppreference.com/w/cpp/26
Overview of contracts design history in C++
https://en.wikipedia.org/wiki/Contract_programming
General background on C++ language evolution and standardization process
https://isocpp.org/std/status
Rust memory safety model (for comparison context)
https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html