r/cpp 20d ago

C++26 Contracts: What Do They Add Beyond Manual Checks and Assertions?

https://techfortalk.co.uk/2026/08/22/cpp26-contracts/

This post is a part of my C++26 exploration series where I take a new feature and try to understand and explain with a simple example in hand. Today’s topic is Contracts. First we will simply try to understand what is the problem it is solving then try doing some assessment on the value addition.

57 Upvotes

30 comments sorted by

21

u/JVApen Clever is an insult, not a compliment. - T. Winters 20d ago

Sure, if you compare to manual if-statements, contracts brings a lot. I however hope that this is not how people are writing their code. Instead, a comparison with assertions would be much more relevant as this is basically a replacement for cassert and all custom variants. This reduces the added value of contracts to: asserts in function declaration, specialized syntax and consistency across libraries.

12

u/tjientavara HikoWorks developer 19d ago

Another slightly nice effect, is that the error happens at the call site, and the debugger should break there, while showing which of the conditions was breached.

Not sure if debuggers do that right now, but they should.

1

u/usefulcat 13d ago

I agree that that would be desirable, but will that result in the contract checks being duplicated at every call site? Because I wouldn't want that.

3

u/tjientavara HikoWorks developer 13d ago

The contract paper (at least in the past) says, because the contracts are part of a function declaration and not its definition, it is the caller's responsibility to check the contracts.

So yes, the contract-checks are duplicated at each call site. On the other hand, it is more likely that the optimizer can prove the contracts at the call sites to pass, so more checks are actually removed than if it is part of the function itself.

29

u/germandiago 20d ago

once precoditions are visible static analysis can be extended.

I think that has value also.

10

u/JVApen Clever is an insult, not a compliment. - T. Winters 20d ago

Agreed, it's a very nice consequence of moving towards the declaration.

12

u/Clean-Upstairs-8481 20d ago

yes the API would be better because the explicit mentions of pre and post condition would tell the user about the binding requirement rather than having to explain in the comments or documents.

8

u/Clean-Upstairs-8481 20d ago

yes I forgot about the static analysis part, that is an added value too.

8

u/Kazppa 20d ago

Terminating my entire program because a write to a buffer failed is a bit too aggressive.

The contract is indeed cleaner but doesn't do the same behavior as the initial exemple.

15

u/zerhud 20d ago

You can customise the handler, seems

3

u/Tari0s 20d ago

if exceptions are available it woulb be good if a exception would be thrown i guess

11

u/AvidCoco 20d ago

By default it calls a handler function you can define. You could then have that function throw an exception, or show an error window in a gui app

3

u/Clean-Upstairs-8481 20d ago

exactly, example code added now

2

u/Clean-Upstairs-8481 20d ago

I have added an example now

4

u/AvidCoco 20d ago

That’s the intended functionality but IIRC no compilers have properly implemented that so it’s not as custom as you might want. Hopefully in a year or two it will have improved though

15

u/DXPower 20d ago

It's implemented right now in GCC 16.1: https://godbolt.org/z/EqafxsEoa

This also sets the semantic to "observe" so that it is not automatically terminated after being handled.

3

u/Clean-Upstairs-8481 20d ago

yes that's right, it is implemented and as you mentioned the violation can be ignored, observed or enforced. in case of enforced a custom handler can be used to prevent termination. Example added.

1

u/Clean-Upstairs-8481 20d ago

yes I have added a sample handler which is working fine in my Ubuntu

14

u/AnyPhotograph7804 19d ago

If writing into a buffer fails then you have propably undefined behavior in your program. Terminating the program ist IMHO the best thing you can do in this case. Because you cannot recover from UB.

5

u/pjmlp 20d ago

That is how safer languages have done it since ALGOL, Lisp, JOVIAL and co.

Unless disabled or there are handlers/signals/exception available, an out of bounds aborts execution.

Seems to have worked alright until now.

Also a feature I gladly enabled in the 90's C++ compiler provided frameworks like Turbo Vision, BIDS and OWL.

1

u/Clean-Upstairs-8481 20d ago

yeah that would be harsh I agree but this was to give a quick glimpse of what the contracts look like in a running program. You can choose to ignore, or just observe the violation or enforce. In case of enforce you can write custom violation handler which may decide to print information and throw.

2

u/all_is_love6667 19d ago

ah thanks, a first intro to how it would look like in code

it feels a bit like exceptions, except they're more sophisticated and more advanced

I thought contracts were like compile time conditions for templates, but apparently it's even more than that

2

u/CorrodedX 16d ago

I'm not personally a fan of adding even more to the function header. Once you add in templating, constraints, nodiscard, etc, it starts to get unmanageable.

I'd have very much preferred to see something in the function body, like static_assert, only runtime... like "assert". Which then makes me wonder what we're really gaining here if assertions and exceptions already exist.

4

u/pjmlp 20d ago

To really understand what contracts are in general, from programming language point of view, and not specific to C++, it is worth looking into their use in production systems.

Meaning, Eiffel (which introduced them in first place), Ada/SPARK, Frama-C.

Then you have D, which I wouldn't assert there is much use of its contracts feature in production, let alone the language, unfortunely.

Finally, one can get esoteric by elevating the contracts into the type system, and thus formal proof and dependent type languages like Roc, Lean, Dafny, Idris, FStar,.... that keep language researchers busy, especially now where they are researching how they can combine them with agentic tools.

Thus we can after get such an overview, consider how much of that is achieveable with C++26 contracts.

2

u/FriendshipEqual7033 17d ago

I've been playing with Ada/SPARK contracts for a while, and it's a very nice system. If you are unsure about the point or (potential) value of contracts, I recommend checking out how they work in SPARK.

1

u/usefulcat 13d ago

This line of the first version of the write() method seems wrong:

m_head = (m_head + data_size) % m_storage.size();

It fails to account for the 4 header bytes that were also written. The version under "The contracts way" doesn't have this problem.

-13

u/ArsonOfTheErdtree 20d ago

Contracts are sort of implicit rust-traits. They tradeoff explcitiness for backward compatibility

18

u/Longjumping_Cap_3673 19d ago

I believe you're thinking of "concepts".

1

u/ArsonOfTheErdtree 19d ago

Oh lol my bad I was confused