C++ Logo

std-proposals

Advanced search

Re: [std-proposals] compile_assert() a static assert that fires at compile time, not runtime.

From: Jonathan Grant <jg_at_[hidden]>
Date: Thu, 5 Mar 2026 01:01:10 +0000
Hi Jan

On 19/02/2026 15:43, Jan Schultke via Std-Proposals wrote:
> Also, I don't think that having this feature would have made contracts less necessary. None of the current contract evaluation semantics do what OP is asking for. However, it would be possible to add a fifth "proof" contract evaluation semantic, one step up from ignore. That makes it seem to me like what OP proposes provides additional motivation for contracts in their current state, since our C++26 design could be extended to provide everything OP is asking for.
>
>
> Now thinking about, making compile_assert a use of contract_assert with "proof" contract evaluation semantics also solves the issue of optimization levels.

I like this idea, a new level "proof", beyond "enforce" maybe that is the runtime approach.

 
> The user can control what contract evaluation semantic is chosen using build flags, just like optimization levels. To prevent unusable debug builds, the user could simply use ignore or enforce semantic on debug builds (with -O0) and "proof" semantic on optimized builds (-O3) instead of ignore. If the feature is tied to contract semantics, we don't need to introduce a notion of optimization levels into the standard.

This is a good idea. that "proof" could only work in optimized builds, so debug could be runtime enforcement. Or I don't mind compiling my debug builds with -O1/-O2 (maybe enough?). I'd suggest to call it "prove" BTW

> Not to pat myself on the back too much, but I think this is brilliant.
>

Sounds good!

Could the ignore/observe/enforce/prove be set by a build macro?

I did wonder, when enforced at compile time, the build stops. When enforced at runtime, the handler is called?

void contract_violation_handler(const contract_violation& v);

Seems like as it is noreturn, it can only log, or call std::terminate()
If it was allowed to throw, at least could throw std::runtime_error? It may be that those would just be logged, and the module may not be restarted, eg if it was a printer monitor. It could be that printing was no longer available, or the programmer would need to put in a retry mechanism.

I added two examples showing how compile_assert could do contracts at compile time, just my examples, these aren't real programs.

#define pre(expr) compile_assert(expr, "")
#define contract_assert(expr) compile_assert(expr, "")
#define post(expr) compile_assert(expr, "")

A percentage number class
https://github.com/jonnygrant/compile_assert/blob/main/testsuite/main28_a.cpp

A bank_account class
https://github.com/jonnygrant/compile_assert/blob/main/testsuite/main25_a.cpp


I'd like to try out C++ Contracts, is there a compiler that has <contracts> and support yet?

Regards
Jonathan

Received on 2026-03-05 01:01:18