<div dir="auto"><div><br><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Mon, 30 Mar 2026, 12:07 David Brown, &lt;<a href="mailto:david.brown@hesbynett.no">david.brown@hesbynett.no</a>&gt; wrote:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
I don&#39;t really agree with the distinctions made in that paper.  But <br>
perhaps that is just my background and the kind of programming I do. <br>
The standards must be general, and must err on the side of conservative <br>
choices.  However, I think it is important to understand there are <br>
different viewpoints here, and different needs.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Yes, and contracts and assumptions are two different features that suit those different needs. </div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
To me, it is a natural thing that a function has a pre-condition and a <br>
post-condition.  The caller guarantees that the pre-condition is <br>
fulfilled.  The function can assume that the pre-condition is fulfilled, <br>
and uses that to ensure the post-condition is fulfilled.  The caller can <br>
then assume that the post-condition is fulfilled.  That is the whole <br>
point of the process - it is what gives meaning to programming.  A <br>
&quot;function&quot; is something that, given suitable inputs, produces suitable <br>
outputs.  (To handle side-effects, we can pretend that &quot;the world before <br>
the call&quot; is an input and &quot;the world after the call&quot; is an output.  That <br>
is not very practical for writing pre and post conditions in C++, but <br>
it&#39;s fine for talking about the theory.)<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">You&#39;re describing contracts.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
I am hugely in favour of being able to have the language (compiler, <br>
run-time support, etc.) check for correctness at compile time, as much <br>
as practically possible.  For run-time checks, a balance must always be <br>
found - it is good that it is easy for the programmer to enable checks, <br>
but also important that checks can be disabled easily.  For a lot of C++ <br>
code, efficiency is not particularly important - but for some code it is <br>
vital.  So having compiler options (standardised where possible and <br>
practical) to modify these balances is a good idea.  Even the best <br>
programmers make mistakes, and tools that help find these mistakes are <br>
always helpful.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Still describing contracts. </div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
However, I feel that a lot of the discussions about contracts is putting <br>
things in the wrong place, and misunderstanding what such function <br>
specifications mean in different places.  In particular, it is about <br>
responsibilities.<br>
<br>
The pre-condition of a function specifies the caller&#39;s responsibility. <br>
The p2064 paper says the function cannot assume the pre-condition is <br>
correct, because it is code written by someone else that determines if <br>
it holds.  It is, IMHO, precisely because the code is written by someone <br>
else that the function author should be able to assume the pre-condition <br>
holds.  It is not their job to get the function inputs correct. </blockquote></div></div><div dir="auto"><br></div><div dir="auto">So why bother with contracts then? If the caller has to do it and the callee should not check, a comment works well enough. You don&#39;t need a language mechanism for checking.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> It is <br>
not the function author&#39;s job to hand-hold the caller, or figure out if <br>
the caller has done a good job or not.  It is not the job of the hammer <br>
to determine if the user is likely to hit their thumb rather than the <br>
nail - or if the user is trying to hammer in a screw.  The function <br>
author should be free to assume the pre-condition holds - likewise, the <br>
compiler optimiser can assume it holds true.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">So just assume bugs never happen, undefined behaviour never happens, and optimize based on that assumption. What could go wrong? </div><div dir="auto"><br></div><div dir="auto">I think we have enough experience with non-memory-safe language by now to know that isn&#39;t a great approach.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
On the caller side, it is the caller author&#39;s job to make sure the <br>
pre-condition is fulfilled.  If it needs to be checked at run-time (and <br>
such checks can be vital in development and debugging, and often worth <br>
the cost even in final releases) then it should be done on the caller <br>
side.  After all, if the pre-condition is not satisfied, it is the <br>
caller code that is wrong - not the function implementation.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">This is a valid point of view, but not how C++ contracts are defined. The checks might run on the caller side, or the callee side, or both. </div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
The inverse applies to the post-condition.  The caller code can assume <br>
the post-condition is true (unless the caller has messed up and not <br>
satisfied the pre-condition).  The function implementation is <br>
responsible for satisfying the post-condition, and therefore any checks <br>
should be done at that point.<br>
<br>
Getting this wrong is a waste of everyone&#39;s time.  It is a waste of the <br>
developer&#39;s time, whether they are implementing the caller or the <br>
callee.  It is a waste of run-time at both sides.  It can ruin the <br>
analysability of code.  Suppose you have this function :<br>
<br>
double square_root(double x)<br>
pre (x &gt;= 0)<br>
post (y : abs(y * y - x) &lt; 0.001);<br>
<br>
When treated correctly, this is a pure function.  There are no <br>
side-effects.  It is a complete function - it gives a correct result for <br>
any valid input.  There are no exceptions.  Implementations can be <br>
efficient, calls can be optimised (such as moving it around other code, <br>
eliminating duplicates, compile-time pre-calculation, etc.). <br>
Correctness analysis by tools or humans is straightforward, both for the <br>
function itself and for caller code.  There is no undefined behaviour in <br>
the function - a call to &quot;square_root(-1)&quot; is undefined behaviour in the <br>
caller.<br>
<br>
But if the implementation cannot assume the pre-condition is true, this <br>
is all gone.  At best, you now have UB in the function, because you have <br>
declared that it is possible to call the function with a negative input. <br>
  At worst, the function implementation now comes with a check leading <br>
to a logging message, program termination, a thrown exception, or some <br>
other such effect.  Now the function implementer has to think about how <br>
to handle incompetent callers. </blockquote></div></div><div dir="auto"><br></div><div dir="auto">Why? If it&#39;s using contracts, which your declaration does, then that&#39;s all clearly handled via the contracts feature. The implementer doesn&#39;t have to recreate all of that handling.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Callers have to think about how the <br>
function interacts with other aspects of the code - the function may <br>
crash the program, or interact badly with threading.<br>
<br>
If the function implementer cannot trust code to call it correctly, and <br>
function callers cannot trust function implementers to code correctly, <br>
then the whole concept of programming falls apart. </blockquote></div></div><div dir="auto"><br></div><div dir="auto">This is just hyperbole. The point of contracts (or manually checking with `assert` or similar checks) is to limit the damage when bugs like that happen. It allows the program to work without trusting that no bugs are present anywhere.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Every function <br>
becomes a paranoid code snippet that must double-check and triple-check <br>
everything, including the function calls used to check the function calls.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">You are again describing why contracts are useful.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
<br>
There are, of course, points in code where you do not trust others.  You <br>
don&#39;t trust data coming in from outside.  You don&#39;t trust caller inputs <br>
at API boundaries, at least for &quot;major&quot; functions or where the <br>
consequences of errors can be significant.  But if you can&#39;t trust code <br>
internal code and function calls, everything falls apart.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">OK. So don&#39;t use contract checks at those internal points.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
And if &quot;pre&quot; and &quot;post&quot;, along with contract assertions, cannot be <br>
assumed to be satisfied (without optional checks to aid debugging), then <br>
they are IMHO pointless in almost all code. </blockquote></div></div><div dir="auto"><br></div><div dir="auto">This is a ridiculous claim.</div><div dir="auto"><br></div><div dir="auto">C++ contracts are not just about debugging, they&#39;re also about being defensive to prevent undefined behaviour from bugs. Not every program can just be re-run in a debugger with identical inputs to find where a bug happened. And even if they can, if the bug already happened in production, it might be too late. Debugging after the fact doesn&#39;t prevent the UB from having already happened. Some people want to enable contracts in production to defend against bugs that haven&#39;t been tested for or haven&#39;t been envisioned during development.</div><div dir="auto"><br></div><div dir="auto">And since the version of contracts we have in C++26 only allows them to be enabled globally or disabled globally, for the whole program, you don&#39;t get to choose which API boundaries have checks enabled and which don&#39;t. So you can&#39;t use contract checks as performance hints in your code without disabling checks at API boundaries between untrusted (or less trusted, or less tested) components.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> I would prefer to be able <br>
to add these freely in all sorts of code, even when I control both <br>
caller and callee - specifications written in C++ are preferable to <br>
specifications written as comments.  I had hoped that C++26 contracts <br>
would let me write clearer code, have better static checking, have <br>
optional run-time checking on chosen functions while debugging, </blockquote></div></div><div dir="auto"><br></div><div dir="auto">You have all that. </div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">and lead <br>
to more efficient generated code. </blockquote></div></div><div dir="auto"><br></div><div dir="auto">That&#39;s not what they&#39;re for. This is a misalignment between what you want and what they do. </div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> I had hoped it would lead to <br>
programmers being clearer about their responsibilities - focusing more <br>
on getting their own code right, rather than how they should deal with <br>
other people&#39;s mistakes.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">You do get that with contracts. </div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
C++ is, of course, a language designed for the needs of a huge number of <br>
programmers with a huge variety of needs and wants - any single <br>
developer is going to have things they like and things they dislike <br>
about it.  But I do wonder if contracts, assertions and assumptions have <br>
hit the best balance here.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">We have separate features for checking contracts at API boundaries and for stating assumptions that the compiler cannot verify by itself. That seems like exactly the right balance, because they&#39;re separate things. So separate features makes sense.</div><div dir="auto"><br></div><div dir="auto">It has been shown repeatedly that turning all assertions into assumptions *decreases* performance in many (or even most) cases. </div><div dir="auto"><br></div><div dir="auto">You get better performance by carefully profiling and adding assumptions only where it really helps, not by overloading the compiler with too many branch predictions. That is orthogonal to contract checking, which is about correctness and verification, not performance. </div><div dir="auto"><br></div><div dir="auto"><br></div></div>

