C++ Logo

std-proposals

Advanced search

Re: [std-proposals] P4334R0 C++ Contracts

From: Peter Bindels <dascandy_at_[hidden]>
Date: Sun, 16 Aug 2026 01:41:54 +0200
Hi Jonathan,

On Sat, Aug 15, 2026 at 11:31 PM Jonathan Grant via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Hello
>
> Sharing my notes and feedback after reading.
>
> I read P4334R0:
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4334r0.pdf
>
> Is it possible to review/reconsider P2900 until this approach for
> Contracts have had more time for field use?
>
> BTW, there is also a broken (404) link in P4334R0 to D4324R0:
> https://isocpp.org/files/papers/D4324R0.html
>
> Could someone point me to the paper?
>
> I read P4332R0 too
> https://isocpp.org/files/papers/P4332R0.html
>
> I have some concerns about C++ Contracts.
>

Please do try it out. It's available on any machine that can install GCC16.
There is also a Clang fork that implements most of it, that is not merged
to mainline but that is being actively worked on in two directions - one to
extend it, and one to merge it to main.

One of the papers says it's not implemented - I don't understand how they
cannot see GCC16 existing since March, in a paper written in August. It
makes you doubt the other statements in the paper, even though there are
some valid concerns in there.

With regards to actual use of it, many people I talk to are indeed trying
it out, and finding it very useful. Quoting from two people's unprompted
statements:

> Once you set up the initial callback function the syntax around it seems
to be really quite simple

> They really are. I'm finding they're bloody useful.

I have been looking into the quality of implementation, and there are a few
bugfixes pending on GCC still.

I have also looked at what constification would mean for an actual codebase
in P3268, and tried it in my personal codebase of about 50kloc, where it
found one ICE in both the GCC and Clang implementations (Clang is
unmerged), and about 10 bugs in my code. Not a widespread rollout, true,
but experience nevertheless. That specific ICE was fixed this week for a
future release.

We can postpone contracts until after more experience is gained, but that
does cause issues for further development on contracts, and on anything
else that tries to rely on their specification for runtime checks and
failure handling. Nothing insurmountable, but unpleasant nonetheless.

At a conceptual level, contracts are Hoare logic: precondition, command,
> postcondition. That underlying idea is simple, whereas the C++ Contracts
> specification appears far more complicated.
>
> If there was scope to consider a simpler approach, which places emphasis
> on compile-time checks that would be very useful for functional safety.
> Runtime checks are risky.
>
> Relying upon a contract violation being detected at runtime has issues.
> The violation may occur only after deployment, and runtime checks may
> potentially be marked 'ignore'. The contract-violation handler also
> introduces a runtime path which cannot necessarily be shown at compile time
> to be unreachable. For functional safety, it's an unknown, if it will be
> called.
>
> This is relevant to functional-safety software, where it is important to
> demonstrate that a violation handler cannot be called, rather than relying
> on it to catch a violation at runtime. Which leaves the question what to
> do, when it is called. Hard to prove, if the symbol is present and linked
> to.
>
> My own proposal, compile_assert(), P4021, explores a different approach:
> https://wg21.link/P4021
>
> compile_assert() operates at compile time and deliberately has a very
> small implementation model. Naturally, it can only verify properties which
> the compiler is able to determine at compile time.
>
> As an experiment, I have implemented contract-like checks in terms of
> compile_assert().
>
> https://github.com/jonnygrant/compile_assert/blob/main/testsuite/main28_a.cpp


compile_assert, if I understand it correctly, is identical to contracts in
P2900 when set up to have a C++ library that does not implement its
violation handler function. Your program will link if and only if it could
be proven during compilation. That already works like that - in fact, I at
first didn't notice I had forgotten to switch over to my experimental
libc++ until it failed to link after adding a few contracts. The first few
in the places they were called were always true and didn't emit a symbol to
link to in the first place.

With regards to proving things at compile time, the current definition of
contracts is enough for simple assertions. Anything that is too complicated
(lamdbas, usually) or that passes through an opaque interface that the
compiler cannot see into, cannot be optimized. In particular, a sequence
f(g(x)) where both g(x) has a postcondition r:p(rv) and f(r) has a
precondition p(r), cannot forward the result of a postcondition on g(x) to
f, as there is no way to explain that evaluating p with the same argument
twice will do the same thing twice. For repeated checks on a precondition
we have taken that allowance into the standard, but for this specific
situation we'd need something like [[reproducible]] or [[unsequenced]] as
in C.

Beyond that, I know that multiple different groups of people are looking
into what specifically we can do with contracts as specified, and what we'd
need to change or add. So far the results seem to be that it works well
enough, but that with minor tweaks we can make it more powerful. A
hypothetical [[mustprove]] attribute could exist in a compiler, requesting
it to fail the build if it cannot prove a functions' calls' pre-contracts,
and its postcontract, based on its own pre-contracts and its calls'
postcontracts. Basically, asking the compiler to do the Hoare propagation
and seeing if it connects, at a semantic level that would need to be done
early on in a compiler. Given such information, depending on build modes, a
compiler can just remove all checks in that function, as there's no way
they don't hold. Will never be able to do all code - but if it can do 95%
of the code, I'll happily review or rewrite the remaining 5%. Think of it
like a borrow checker for the guarantees that brings, except functional
safety (and whatever memory safety was expressed in contracts).


But let's first see what happens with the C++26 DIS. If you want to form an
opinion on how well it works, try it out - godbolt, local install - and
form your own opinion. And if you'd like it to have more features maybe
consider not voting against for that reason. That's not going to get you
more features - it's only going to cause more turbulence and delay.

Regards,
Peter

Received on 2026-08-15 23:42:12