I was reading about contracts in Thoughts about C++17 by B. Stroustrup and assisted a small presentation talking about them but I am not sure I have understood them really.
So I have a some interrogations and if it is possible to illustrate them with some examples :
Are contracts just a better replacement of the classic
assert()
and should they be used together ? What contracts really are put in simple terms for a software dev ?Would contracts have an impact on how we handle exceptions ? If yes, how should we use exceptions and contracts ?
Would using contracts imply an overhead at execution time ? Will we be allow to deactivate them on release code ?
Edit from the proposal N4415 :
A pre-condition contract of the indexing operator of a Vector class could be written:
T& operator[](size_t i) [[expects: i < size()]];
Similarly, a post-condition contract on a constructor of an ArrayView class could be expressed as:
ArrayView(const vector<T>& v) [[ensures: data() == v.data()]];
I started with the link from the original document OP provided. There are some answers, I suppose. I strongly recommend to start with that paper. Here is TL&DR version:
About your questions:
and example:
In my opinion, this is just nice and readable.
In pre-condition contracts exceptions still can be used, as further behavior after pre-condition contract failure is not guaranteed.
Some use cases (as I can suppose while i am not even close to developing a contracts design)
assert()
as contracts are more readable and can be optimized at compilation time.There are also some other suggestions about contracts implementation, so our investigation is just premature.
It is not easy to answer your questions other that with: It depends. This is because it is not yet clear what contracts are going to be exactly. There are several proposals and ideas floating around right now:
n4378 Lakos et al. basically proposes to standardize a sophisticated assert toolkit. Contracts are checked inside of a functions implementation, 3 different assert levels are provided to control the amount of runtime checks and the handling of assert violations can be customized.
n4415 dos Reis et al. and n4435 Brown are fairly similar and propose a attribute based syntax to define pre and post conditions in the functions interfaces. They do not go into details on how much control they give over run-time checks and the behavior on violations.
There have been less recent papers on this topic, too. There are many details which are not yet decided, and this feature touches many different areas (e.g. modules, optimization, building/linking) over some of which the standard has little control.
Your question on exceptions is particularly difficult, because the interactions between contract violation handling and exceptions is unclear (e.g. could a contract violation handler throw (useful in test frameworks)? what if the function is
noexcept(true)
?).As far as I've read from this document: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf
Contracts do what
assert
has been trying to do in a primitive way for years. They're both documentation and a run-time assert of how the caller should be expected to call the function and in what state can the caller expect the code to be after the function has returned. Those are usually known as pre-conditions and post-conditions, or invariants.This helps clean up code on the implementation side, because with contracts we can assume that once the execution has gone inside your function, your arguments are in valid state (what you expect them to be).
The post-conditions part might change how you handle exceptions, because with contracts you will have to make sure that throwing an exception won't break your post-conditions. This usually means that your code has to be exception safe, though whether that means strong exception guarantee or basic guarantee depends on your conditions.
Example:
In this example here, if
new
orData
's constructor throws an exception, your post-condition is violated. This means that you should change all such code to make sure your Contract is never violated!Of course, just like
assert
, contracts might include a run-time overhead. The difference though is that since contracts can be put as part of the function's declaration, the compiler can do better optimizations, such as evaluating the conditions at the caller's site or even evaluate them at compile time. Section 1.5 of the document mentioned at the beginning of this post talks about the possibilities of turning off contracts depending on your build configuration, just like plain old asserts.