C++ Logo

sg15

Advanced search

Re: [isocpp-sg15] [isocpp-sg21] P3835 -- Different contract checking for different libraries

From: Herb Sutter <herb.sutter_at_[hidden]>
Date: Fri, 17 Oct 2025 06:28:27 -0700
Harald asked:

> On the internet I saw someone saying

>

> void fun(Foo* ptr) pre (ptr!=nullpter), pre(ptr->hasData()) { ... }

>

> might be a problem (for the second pre) and should be written like this

>

> void fun(Foo* ptr) pre (ptr!=nullpter && ptr->hasData()){ ... }

>

> is that true?

 

With ignore, enforce, or quick_enforce there’s no issue. The second check will not be evaluated, no UB.

 

With observe semantics (only), if the pointer is null then:

* the first check fails, and gives a contract violation so you know it was violated
* the second check then gives UB (no time travel, does not affect the first check that already happened)

 

IMO the issue isn’t about contracts, it’s about short-circuit evaluation. This kind of issue can come up generally in the language if you split the (p) and (p->foo()) conditions, so we already teach that to get short-circuit evaluation you need to write the && using (p && p->foo()).

 

This also comes up (again, generally throughout the language) with other examples like

 

               (is_sorted(v) && binary_search(v, x))

 

because implementations of binary_search might try to perform unsafe out-of-bounds access if the range is not already sorted.

 

In case it's helpful, here's the current slide I teach about that example (updated and extended since CppCon):

 



 

Herb

 

 


Received on 2025-10-17 13:28:30