← Back to context

Comment by nananana9

4 days ago

Where do I put these?

If I put them in the header, I have to include half the world because I can't forward declare `Foo foo` argument if I want to check `foo.size() > 3` or similar in a pre/post-condition. This is a non-starter, keeping headers lean is the only way to not end up with 1 hour compiles.

If I put them in the cpp, they lose their only advantage over asserts - that they also double as documentation in the headers.

Did we add 50 pages to the standard for a slightly fancier assert? I feel like this could've been one builtin and a footnote:

contract_assert(expr) - if expr evaluates to false, the behavior of the program is undefined. Implementations are encouraged to emit a runtime check for this in debug builds, or a compiler error in cases where they can statically determine, that the assert will fail.

I'm expecting to see talks (and buy books, read blogs...) in 3 years by someone who spent a lot of work adding contracts to a small but significant code base. This is the type of question they will answer.

I think the right answer is in the header, and in turn that means someone needs to answer your objection - how do you avoid long compiler times? I suspect modules is a large part of the answer, which means the guide/talk will also be how to make modules work in the real world. Remember though, that is all guesses I wouldn't be surprised if I'm wrong.

  • C++ contracts design is based on an internal Bloomberg framework, see John Lakos recent talks on contracts.

    • Hmm, I thought I had watched all his talks on contracts by now, but I must have missed a few (which isn't a surprise - there are a lot of conferences out there that I can't watch them all and get anything done. I end up ignoring a lot of them)

      3 replies →

Strictly speaking you put them in the header.

The first declaration of a function must include the contract pre/post conditions and follow-up re-declarations of the function must either not include any contract conditions or the same conditions as the initial declaration.

And you can avoid re-including the world because pre/post conditions should be externally visible behavior or call out to functions for pre/post checks on internal behavior.

Essentially you either define them using what you have in scope during the initial declaration or you call out to a function located elsewhere that can have access to more/internal scope and do more complicated checks.

Since this is for C++26, you use modules.

  • I live mostly in the real world, unfortunately.

    If new major C++ features will require modules in order to work, I may as well stop following the specs.

    • In the real world, VC++ and clang with MSBuild, CMake/ninja already have good modules support, GCC 16 only has a few issues to iron out.

      By the time C++26 actually becomes available, all three major compilers will already have good modules support.

      Anyone using recent Office versions, is a consumer of a product that makes use of C++ modules today.