C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Using [[assume]] attribute in contracts pre() and post() blocks

From: David Brown <david.brown_at_[hidden]>
Date: Mon, 24 Aug 2026 15:16:27 +0200
That is the way contracts /should/ work, IMHO, but not the way that they
/do/ work. Having had Tony Hoare as the head of department during my
university education, it is a great disappointment to me that C++
contracts look like Hoare logic pre-conditions and post-conditions, but
are actually more like glorified assert macros.

(I am aware that opinions differ, and the folks behind C++ contracts -
specifications and implementations - are smart, experienced developers
who have thought long and hard about this all. This is disappointment
and frustration with what I think this feature could have been, from my
own viewpoint of how I personally want to write code. Maybe what I want
would not be possible or practical in the very wide context of general
C++ development.)

To me, the obvious point of declaring "foo" to have pre() and post()
blocks is that the caller of "foo" should have optional checks that
"pre" holds, the implementation of "foo" should be written and optimised
with the assumption that "pre" holds, the implementation of "foo" should
have optional checks that "post" holds, and the caller of "foo" should
be written and optimised with the assumption that "post" holds.

C++ contracts get a lot of this wrong. Checking is done in the function
definition, which is the wrong place for pre-conditions - if a
pre-condition does not hold, the problem lies in the caller, not the
callee. (Of course the callee can optionally check too, as part of
fault-finding and debugging, or at API boundaries where the caller is
not trusted.) And despite having written out these conditions, and
checked them, the compiler still can't rely on them being true for
optimisation purposes - you have to write [[assume]] again. Having the
pre-condition checks in the wrong place also means that you can't use
"enforce" semantics while testing and debugging a translation unit or
module before switching to "ignored" for code that you are sure is
correct - control of contract evaluation semantics is also in the wrong
place.

At best, C++ contracts are a replacement for "assert" macros on API
boundary functions - IMHO they have missed the opportunity for being a
general tool towards safer and more efficient coding.


Having a convenient way to "assume" that contracts hold would definitely
be useful. I am not sure what the best syntax would be (or to be more
honest, I haven't a clue about the best syntax), but what I would like
to see is a way to do:

1. In the function's declaration, say that the caller must check the
pre-condition.

2. In the function's declaration, say that the caller can assume the
post-condition holds when optimising.

3. Let the function implementation assume the pre-condition holds. This
could be either as a general "it always holds" indication, but might be
better as a "assume pre-conditions hold at this point in the function
implementation". That could allow certain specific checks before the
assumption.

4. Let callers and callees override or dictate the contract enforcement
semantics, and do so separately for pre and post conditions.


David



On 24/08/2026 13:57, Sebastian Wittmeier via Std-Proposals wrote:
> From the view of the function a pre-condition can be assumed, a post-
> condition has to be ensured with the code in the function.
>
> And the opposite for the caller.
>
> -----Ursprüngliche Nachricht-----
> *Von:* Light And Ray via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Mo 24.08.2026 12:57
> *Betreff:* [std-proposals] Using [[assume]] attribute in contracts
> pre() and post() blocks
> *An:* std-proposals_at_[hidden];
> *CC:* Light And Ray <light.and.ray_at_[hidden]>;
> Hello. I'm wanting to make a tiny proposal of syntax, sorry in
> advance if I'm making it wrongly. I will be glad if you correct me
> how to make it correctly, if I make it in a wrong way, or the letter
> is in incorrect format
> I'm learning new C++26 features, contracts in particular. I really
> like the idea, but I don't like that there is no way to treat them
> like a sort of invariant, that programmers can formalize, and
> compilers can optimize. There is an attribute
> [[assume(expression)]], that can be used in a function body for this
> purpose. But it's only about functions bodies. The contracts
> introduce the new syntax where you can place conditions outside the
> body, and it would be nice to allow using this syntax not only for
> asserts, but also for assumes. I'm suggesting this syntax:
> int myFunction(int* ptr)
> pre([[assume]] ptr != nullptr)
> post([[assume]] r : r > 0);
>
> Use [[assume]] attribute without an expression, inside "pre" and
> "post" conditions. What do you think about this? My key idea is to
> share the outside of body syntax with the different meaning of
> postulating pre and post conditions. Instead of "we need to be
> careful that this is always true", it's "I swear it's always true, I
> have validated it mathematically". The both ideas are good in
> different situations, and I think the pre() and post() syntax should
> be available for both of them
>
> Alternatives can be:
>
> Existing [[assume(expression)]] inside pre() and post() blocks, in
> addition to the assert expression:
> int myFunction(int* ptr)
> pre([[assume(ptr != nullptr)]] /* nothing here or the regular
> assert condition */)
> post([[assume(r : r > 0)]]);
> However I don't think it's a good idea to mix assume and assert in
> the same block. And also, assume and assert expressions can, and
> probably will test the same, what's incorrect, because
> after assuming, we cannot expect it to be false
> Or:
> Works as [[assume]] in ignore contracts mode, otherwise as assert:
> int myFunction(int* ptr)
> pre([[assume_on_ignore]] ptr != nullptr)
> post([[assume_on_ignore]] r : r > 0);
> But it's dangerous, because you can have radically different
> behavior in debug and release builds
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>
>

Received on 2026-08-24 13:16:32