C++ Logo

std-proposals

Advanced search

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

From: Light And Ray <light.and.ray_at_[hidden]>
Date: Mon, 24 Aug 2026 18:40:21 +0400
>
> 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 share this sentiment, I also thought it's a formalization of this thing
that always existed - when your function accepts a value, but not any value
of its type, but a strict subset. An invariant. It was always informal. And
when I heard the word "contract", my thoughts went to "Look, you give me
'obj.isValid() == true', I give you the result. Otherwise I can't guarantee
anything. Deal? Deal.". It's like a way to give programmers a tool to
define their own defined behavior boundaries

On the other hand, I understand why the standard developers can not want to
implement contracts in this way. Assumptions can let you generate a ton of
UB out of thin air. And it's maybe a bad idea to give users a 3 letter
syntax for this. My proposal fixes this though, because it uses an
attribute that has association with fine-tuned compiler hints. And also
[[assume]] attribute already exists, but with a different syntax

I'm new in the standards proposals, should I do something beyond these
mailing letters for this syntax to be considered?

On Mon, Aug 24, 2026 at 5:16 PM David Brown via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> 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
> >
> >
> >
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2026-08-24 14:40:38