LorenzoCaminiti lorcaminiti@gmail.com200820092010201120122013201420152016201720182019Lorenzo Caminiti
Distributed under the Boost Software License, Version 1.0 (see accompanying
file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt)
Boost.Contract 1.0.0
Our field needs more formality, but the profession has not
realized it yet.
-- Bertrand Meyer (see [Meyer97]
page 400)
This library implements contract
programming (a.k.a., Design by Contract or DbC)
Design by Contract (DbC) is a registered trademark of the Eiffel Software company
and it was first introduced by the Eiffel programming language (see [Meyer97]).
for the C++ programming language. All contract programming features
are supported by this library: Subcontracting, class invariants (also for static
and volatile member functions), postconditions (with old and return values),
preconditions, customizable actions on assertion failure (e.g., terminate the
program or throw exceptions), optional compilation of assertions, disable assertions
while already checking other assertions (to avoid infinite recursion), and more
(see Feature
Summary).
Introduction
Contract programming allows to specify preconditions, postconditions, and class
invariants that are automatically checked when functions are executed at run-time.
These conditions assert program specifications within the source code itself
allowing to find bugs more quickly during testing, making the code self-documenting,
and increasing overall software quality (see Contract
Programming Overview).
For example, consider the following function inc
that increments its argument x
by 1 and let's write its contract
using code comments (see introduction_comments.cpp):
voidinc(int&x)// Precondition: x < std::numeric_limit<int>::max()// Postcondition: x == oldof(x) + 1{++x;// Function body.}
The precondition states that at function entry the argument x
must be strictly smaller than the maximum allowable value of its type (so it
can be incremented by 1 without
overflowing). The postcondition states that at function exit the argument
x must be incremented by 1 with respect to the old value
that x had before executing
the function (indicated here by oldof(x)).
Note that postconditions shall be checked only when the execution of the function
body does not throw an exception.
Now let's program this function and its contract using this library (see introduction.cpp
and Non-Member
Functions):
#include<boost/contract.hpp>voidinc(int&x){boost::contract::old_ptr<int>old_x=BOOST_CONTRACT_OLDOF(x);// Old value.boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(x<std::numeric_limits<int>::max());// Line 17.}).postcondition([&]{BOOST_CONTRACT_ASSERT(x==*old_x+1);// Line 20.});++x;// Function body.}
When the above function inc
is called, this library will:
First, execute the functor passed to .precondition(...)
that asserts inc precondition.
Then, execute inc body
(i.e., all the code that follows the boost::contract::checkc=... declaration).
Last, execute the functor passed to .postcondition(...)
that asserts inc postcondition
(unless inc body threw
an exception).
For example, if there is a bug in the code calling inc
so that the function is called with x
equal to std::numeric_limits<int>::max() then the program will terminate with an error
message similar to the following (and it will be evident that the bug is in
the calling code):
precondition assertion "x < std::numeric_limits<int>::max()" failed: file "introduction.cpp", line 17
Instead, if there is a bug in the implementation of inc
so that x is not incremented
by 1 after the execution of the
function body then the program will terminate with an error message similar
to the following (and it will be evident that the bug is in inc
body):
In this example the function body is composed of a single trivial instruction
++x
so it easy to check by visual inspection that it does not contain any bug
and it will always increment x
by 1 thus the function postcondition
will never fail. In real production code, function bodies are rarely this
simple and can hide bugs which make checking postconditions useful.
postcondition assertion "x == *old_x + 1" failed: file "introduction.cpp", line 20
By default, when an assertion fails this library prints an error message such
the ones above to the standard error std::cerr and
terminates the program calling std::terminate
(this behaviour can be customized to take any user-specified action including
throwing exceptions, see Throw
on Failures). Note that the error messages printed by this library contain
all the information necessary to easily and uniquely identify the point in
the code at which contract assertions fail. Rationale: The assertion failure message
printed by this library follows a format similar to the message printed by
Clang when the C-style assert
macro fails.
C++11 lambda functions are necessary to use this library without manually
writing a significant amount of boiler-plate code to program functors that
assert the contracts (see No
Lambda Functions). That said, this library implementation does not
use C++11 features and should work on most modern C++ compilers (see Getting Started).
In addition to contracts for non-member functions as shown the in the example
above, this library allows to program contracts for constructors, destructors,
and member functions. These can check class invariants and can also subcontract
inheriting and extending contracts from base classes (see introduction_public.cpp
and Public
Function Overrides):
The pushable base class is
used in this example just to show subcontracting, it is somewhat arbitrary
and it will likely not appear in real production code.
template<typenameT>classvector#defineBASESpublicpushable<T>:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// For subcontracting.#undefBASESvoidinvariant()const{// Checked in AND with base class invariants.BOOST_CONTRACT_ASSERT(size()<=capacity());}virtualvoidpush_back(Tconst&value,boost::contract::virtual_*v=0)/* override */{// For virtuals.boost::contract::old_ptr<unsigned>old_size=BOOST_CONTRACT_OLDOF(v,size());// Old values for virtuals.boost::contract::checkc=boost::contract::public_function<// For overrides.override_push_back>(v,&vector::push_back,this,value).precondition([&]{// Checked in OR with base preconditions.BOOST_CONTRACT_ASSERT(size()<max_size());}).postcondition([&]{// Checked in AND with base postconditions.BOOST_CONTRACT_ASSERT(size()==*old_size+1);});vect_.push_back(value);}BOOST_CONTRACT_OVERRIDE(push_back)// Define `override_push_back` above.// Could program contracts for those as well.unsignedsize()const{returnvect_.size();}unsignedmax_size()const{returnvect_.max_size();}unsignedcapacity()const{returnvect_.capacity();}private:std::vector<T>vect_;};Language
Support
The authors of this library advocate for contracts to be added to the core
language. Adding contract programming to the C++ standard has a number of advantages
over any library implementation (shorter and more concise syntax to program
contracts, specify contracts in declarations instead of definitions, enforce
contract constant-correctness, expected faster compile- and run-time, vendors
could develop static analysis tools to recognize and check contracts statically
when possible, compiler optimizations could be improved based on contract conditions,
etc.).
The [P0380] proposal supports basic contract
programming, it was accepted and it will be included in C++20. This is undoubtedly
a step in the right direction, but unfortunately [P0380]
only supports pre- and postconditions while missing important features such
as class invariants and old values in postconditions, not to mention the lack
of more advanced features like subcontracting (more complete proposals like
[N1962] were rejected by the C++ standard
committee). All contracting programming features are instead supported by this
library (see Feature
Summary for a detailed comparison between the features supported by
this library and the ones listed in different contract programming proposals,
see Bibliography for a list
of references considered during the design and implementation of this library,
including the vast majority of contract programming proposals submitted to
the C++ standard committee).
Full Table of ContentsIntroduction
Full Table of Contents
Getting Started
This Documentation
Compilers and Platforms
Code Organization
Build
Contract Programming Overview
Assertions
Benefits and Costs
Function Calls
Public Function Calls
Constructor Calls
Destructor Calls
Constant-Correctness
Specifications vs. Implementation
On Contract Failures
Feature Summary
Tutorial
Non-Member Functions
Preconditions
Postconditions
Return Values
Old Values
Exception Guarantees
Class Invariants
Constructors
Destructors
Public Functions
Virtual Public Functions
Public Function Overrides (Subcontracting)
Base Classes (Subcontracting)
Static Public Functions
Advanced
Pure Virtual Public Functions
Optional Return Values
Private and Protected Functions
Friend Functions
Function Overloads
Lambdas, Loops, Code Blocks (and constexpr)
Implementation Checks
Old Values Copied at Body
Named Overrides
Access Specifiers
Throw on Failures (and noexcept)
Extras
Old Value Requirements (Templates)
Assertion Requirements (Templates)
Volatile Public Functions
Move Operations
Unions
Assertion Levels
Disable Contract Checking
Disable Contract Compilation (Macro Interface)
Separate Body Implementation
No Lambda Functions (No C++11)
No Macros (and No Variadic Macros)
Examples
Reference
Release Notes
Bibliography
Acknowledgments
Getting Started
This section shows how to setup and start using this library.
This
Documentation
Programmers should be able to start using this library after reading the
Introduction, Getting
Started, and Tutorial.
Other sections of this documentation (e.g., Advanced
and Extras) can be consulted
at a later point to gain a more in-depth knowledge of the library. Contract Programming
Overview can be skipped by programmers that are already familiar with
the contract programming methodology.
Some of the source code listed in this documentation contains special code
comments of the form //[...
and //]. These mark sections
of the code that are automatically extracted from the source code and presented
as part of this documentation. Rationale: This allows to make sure that
most of the example code presented in this documentation is always up-to-date,
builds and runs with the latest implementation of the library.
It should be noted that the purpose of all examples of this documentation
is to illustrate how to use this library and not to show real production
code.
Some footnotes are marked by the word "Rationale".
These explain some of the decisions made during the design and implementation
of this library.
Compilers
and Platforms
In general, this library requires C++ compilers with a sound implementation
of SFINAE and other template meta-programming techniques supported by the
C++03 standard. It is possible to use this library without C++11 lambda functions
but a large amount of boiler-plate code is required to manually program separate
functors to specify preconditions, postconditions, etc. (so using this library
without C++11 lambda functions is possible but not recommended, see No Lambda
Functions). It is also possible to use this library without variadic
macros by manually programming a small amount of boiler-plate code (but most
if not all modern C++ compilers support variadic macros even before C++99
and C++11 so this should never be needed in practice, see No
Macros).
Some parts of this documentation use the syntax type-of(...)
to indicate an operator logically equivalent to C++11 decltype(...). However, this library implementation
does not actually use type deduction in these cases (because the library
internally already knows the types in question) so support for C++11 decltype and other type-of implementations
are not actually required (that is why type-of
and not the real decltype operator
is used in this documentation).
This library has been developed and tested using:
Visual Studio 2015 on Windows (MSVC cl version 19.00.24215.1).
GCC version 5.4.0 on Cygwin (with C++11 features enabled -std=c++11).
Clang version 3.8.1 on Cygwin (with C++11 features enabled -std=c++11).
For information on other compilers and platforms see the library regression
tests. The development and maintenance of this library is hosted
on GitHub.
Code
Organization
Let boost-root be the directory where
Boost source files were installed. This library flies are organized as follows:
boost-root/libs/contract # Directory where this library files are.
build/ # Build files (using BJam).
doc/ # Documentation (using Boost.QuickBook).
example/ # Examples (also those listed in this documentation).
include/ # DO NOT USE: Use copies of these files from
boost/ # boost-root/boost/ instead:
contract.hpp # - Include all headers at once.
contract_macro.hpp # - Include library macro interface.
contract/ # - Header files that can be included one-by-one.
core/ # - Fundamental headers (usually indirectly included by other headers).
detail/ # - Implementation code (should never be included or used directly).
src/ # Library source code to be compiled.
test/ # Tests.
All headers required by this library can be included at once by:
#include<boost/contract.hpp>
Or, by the following when using the library macro interface (see Disable
Contract Compilation):
#include<boost/contract_macro.hpp>
Alternatively, all boost/contract/*.hpp headers are independent
from one another and they can be selectively included one-by-one based on
the specific functionality of this library being used (but this was measured
to not make an appreciable difference in compile-time so boost/contract.hpp
can be included directly in most cases). The boost/contract/core/*.hpp
headers are not independent from other headers and they do not need to be
directly included in user code when boost/contract.hpp
or boost/contract/*.hpp headers are included already.
All files under boost/contract/detail/, names in the
boost::contract::detail namespace, macros starting with
BOOST_CONTRACT_DETAIL...,
and all names starting with boost_contract_detail... (in any namespace, including user-defined
namespaces) are part of this library implementation and should never be used
directly in user code. Names starting with BOOST_CONTRACT_ERROR... are used by this library to report some
compile-time errors (so spotting these names in compiler error messages might
help troubleshooting).
Build
Let boost-root be the directory where
Boost source files were installed. This library is installed and compiled
as part of Boost using BJam.
It is strongly recommended to compile and use this library as a shared
library (a.k.a., Dynamically Linked Library or DLL) by defining the BOOST_ALL_DYN_LINK macro (or at least
BOOST_CONTRACT_DYN_LINK)
when building Boost. When using BJam to build Boost, this can be achieved
by the link=shared parameter (which is already the
default so no extra parameter is actually needed for bjam).
It is also possible to compile and use this library as a static library
(by defining the BOOST_CONTRACT_STATIC_LINK
macro) or as a header-only library (by leaving both BOOST_CONTRACT_DYN_LINK
and BOOST_CONTRACT_STATIC_LINK
undefined). However, this library is not guaranteed to always work correctly
in these cases. Specifically, this library might not correctly disable
contracts while checking other contracts and call the correct user-defined
contract failure handlers unless it is compiled as a shared library when
it is used across different program units (different programs, different
shared libraries in the same program, etc.).
Linux-Based
Systems
For example, to build all Boost libraries including this one (as shared libraries,
see also Boost
documentation):
$ cd boost-root
$ ./bootstrap.sh
$ ./bjam
To compile and run the boost-root/libs/contract/example/features/introduction.cpp
example:
$ cd boost-root/libs/contract/example
$ ../../../bjam features-introduction
To compile and run all this library's tests (this might take while):
$ cd boost-root/libs/contract/test
$ ../../../bjam
To compile and run code that uses this library but without BJam (similarly
for Clang):
$ cd /tmp
$ g++ -std=c++11 -D BOOST_CONTRACT_DYN_LINK -I boost-rootboost-root/stage/lib/system-prefixboost_contract.dll boost-root/libs/contract/example/features/introduction.cpp -o introduction
$ export PATH=$PATH:boost-root/stage/lib
$ ./introduction
Windows-Based
Systems
For example, to build all Boost libraries including this one (as DLLs, see
also Boost
documentation):
>cd boost-root
>bootstrap.bat
>bjam
To compile and run the boost-root/libs/contract/example/features/introduction.cpp
example:
>cd boost-root\libs\contract\example
>..\..\..\bjam features-introduction
To compile and run all this library's tests (this might take while):
>cd boost-root\libs\contract\test
>..\..\..\bjam
To compile and run code that uses this library but without BJam:
>cd C:\Temp
>cl /MDd /EHs /std:c++11 /D BOOST_CONTRACT_DYN_LINK /I boost-root /link /DLL /LIBPATH:boost-root\stage\lib boost-root\libs\contract\example\features\introduction.cpp /out:introduction
>set PATH=%PATH%;boost-root/stage/lib
>introduction
Contract
Programming Overview
It is absurd to make elaborate security checks on debugging
runs, when no trust is put in the results, and then remove them in production
runs, when an erroneous result could be expensive or disastrous. What would
we think of a sailing enthusiast who wears his life-jacket when training
on dry land but takes it off as soon as he goes to sea?
-- Charles Antony Richard Hoare (see [Hoare73])
This section gives an overview of contract programming (see [Meyer97],
[Mitchell02], and [N1613]
for more extensive introductions to contract programming). Readers that already
have a basic understanding of contract programming can skip this section and
maybe come back to it after reading the Tutorial.
The objective of this library is not to convince programmers to use contract
programming. It is assumed that programmes understand the benefits and trade-offs
associated with contract programming and they have already decided to use
this methodology in their code. Then, this library aims to be the best and
more complete contract programming library for C++ (without using programs
and tools external to the C++ language and its preprocessor).
Assertions
Contract programming is characterized by the following assertion mechanisms:
Preconditions: These are logical conditions that
programmers expect to be true when a function is called (e.g., to check
constraints on function arguments). Operations that logically have no
preconditions (i.e., that are always well-defined for the entire domain
of their inputs) are also referred to as having a wide contract.
This is in contrast to operations that have preconditions which are also
referred to as having a narrow contract (note that
operations with truly narrow contracts are also expected to never throw
exceptions because the implementation body of these operations is always
expected to succeed after its preconditions are checked to be true).
The nomenclature of wide and narrow contracts has gained some popularity
in recent years in the C++ community (appearing in a number of more
recent proposals to add contract programming to the C++ standard, see
Bibliography). This
nomenclature is perfectly reasonable but it is not often used in this
document just because the authors usually prefer to explicitly say
"this operation has no preconditions..." or "this operation
has preconditions..." (this is just a matter of taste).
Postconditions: These are logical conditions that
programmers expect to be true when a function exits without throwing
an exception (e.g., to check the result and any side effect that a function
might have). Postconditions can access the function return value (for
non-void functions) and also old values (which are
the values that expressions had before the function implementation was
executed).
Exception guarantees: These are logical conditions
that programmers except to be true when a function exits throwing an
exception. Exception guarantees can access old values (but not the function
return value). Rationale: Contract assertions for
exception guarantees were first introduced by this library, they are
not part of [N1962] or other references
listed in the Bibliography
(even if exception safety guarantees have long been part of C++ STL
documentation).
Class invariants: These are logical conditions that
programmers expect to be true after a constructor exits without throwing
an exception, before and after the execution of every non-static public
function (even if they throw exceptions), before the destructor is executed
(and also after the destructor is executed but only when the destructor
throws an exception). Class invariants define valid states for all objects
of a given class. It is possible to specify a different set of class
invariants for volatile public functions, namely volatile class
invariants. It is also possible to specify static
class invariants which are excepted to be true before and
after the execution of any constructor, destructor (even if it does not
throw an exception), and public function (even if static). Rationale: Static and volatile class
invariants were first introduced by this library (simply to reflect
the fact that C++ supports also static and volatile public functions),
they are not part of [N1962] or
other references listed in the Bibliography.
Subcontracting: This indicates that preconditions
cannot be strengthen, while postconditions and class invariants cannot
be weaken when a public function in a derived class overrides public
functions in one or more of its base classes (this is formally defined
according to the substitution
principle).
The actual function implementation code, that remains outside of these contract
assertions, is often referred to as the function body
in contract programming.
Class invariants can also be used to specify basic exception
safety guarantees for an object (because they are checked at exit of public
functions even when those throw exceptions). Contract assertions for exception
guarantees can be used to specify strong exception safety
guarantees for a given operation on the same object.
It is also a common requirement for contract programming to automatically
disable contract checking while already checking assertions from another
contract (in order to avoid infinite recursion while checking contract assertions).
This library implements this requirement but in order to globally disable
assertions while checking another assertion some kind of global arbitrating
variable needs to be used by this library implementation. This library
will automatically protect such a global variable from race conditions
in multi-threated programs, but this will effectively introduce a global
lock in the program (the BOOST_CONTRACT_DISABLE_THREADS
macro can be defined to disable this global lock but at the risk of incurring
in race conditions). Rationale:BOOST_CONTRACT_DISABLE_THREADS
is named after BOOST_DISABLE_THREADS.
In general, it is recommended to specify different contract conditions using
separate assertion statements and not to group them together into a single
condition using logical operators (&&,
||, etc.). This is because when
contract conditions are programmed together in a single assertion using logical
operators, it might not be clear which condition actually failed in case
the entire assertion fails at run-time.
C-Style
Assertions
A limited form of contract programming (typically some form of precondition
and basic postcondition checking) can be achieved using the C-style assert macro. Using assert
is common practice for many programmers but it suffers of the following limitations:
assert does not distinguish
between preconditions and postconditions. In well-tested production code,
postconditions can usually be disabled trusting the correctness of the
implementation while preconditions might still need to remain enabled
because of possible changes in the calling code (e.g., postconditions
of a given library could be disabled after testing while keeping the
library preconditions enabled given that future changes in the user code
that calls the library cannot be anticipated). Using assert
it is not possible to selectively disable only postconditions and all
assertions must be disabled at once.
assert requires to manually
program extra code to correctly check postconditions (specifically to
handle functions with multiple return statements, to not check postconditions
when functions throw exceptions, and to implement old values).
assert requires to manually
program extra code to check class invariants (extra member functions,
try blocks, etc.).
assert does not support
subcontracting.
assert calls are usually
scattered within function implementations thus the asserted conditions
are not immediately visible in their entirety by programmers (as they
are instead when the assertions appear in the function declaration or
at least at the very top of the function definition).
Contract programming does not suffer of these limitations.
Benefits
and CostsBenefits
The main use of contract programming is to improve software quality. [Meyer97] discusses how contract programming
can be used as the basic tool to write correct software.
[Stroustrup94] discusses the key
importance of class invariants plus advantages and disadvantages of preconditions
and postconditions.
The following is a short summary of benefits associated with contract programming
inspired mainly by [N1613]:
Preconditions and postconditions: Using function preconditions and postconditions,
programmers can give a precise semantic description of what a function
requires at its entry and what it ensures at its exit (if it does not
throw an exception). In particular, using postcondition old values, contract
programming provides a mechanism that allows programmers to compare values
of an expression before and after the function body execution. This mechanism
is powerful enough to enable programmers to express many correctness
constraints within the code itself, constraints that would otherwise
have to be captured at best only informally by documentation.
Class invariants: Using class invariants, programmers can describe what
to expect from a class and the logic dependencies between the class members.
It is the job of the constructor to ensure that the class invariants
are satisfied when the object is first created. Then the implementation
of the member functions can be largely simplified as they can be written
knowing that the class invariants are satisfied because contract programming
checks them before and after the execution of every public function.
Finally, the destructor makes sure that the class invariants held for
the entire life of the object checking the class invariants one last
time before the object is destructed. Class invariants can also be used
as a criteria for good abstractions: If it is not possible to specify
an invariant, it might be an indication that the design abstraction maybe
be poor and it should not have been made into a class (maybe a namespace
would have sufficed instead).
Self-documenting code: Contracts are part of the source code, they are
checked at run-time so they are always up-to-date with the code itself.
Therefore program specifications, as documented by the contracts, can
be trusted to always be up-to-date with the implementation.
Easier debugging: Contract programming can provide a powerful debugging
facility because, if contracts are well-written, bugs will cause contract
assertions to fail exactly where the problem first occurs instead than
at some later stage of the program execution in an apparently unrelated
(and often hard to debug) manner. Note that a precondition failure points
to a bug in the function caller, a postcondition failure points instead
to a bug in the function implementation.
Of course, if contracts are ill-written then contract programming is
of little use. However, it is less likely to have a bug in both the
function body and the contract than in the function body alone. For
example, consider the validation of a result in postconditions. Validating
the return value might seem redundant, but in this case we actually
want that redundancy. When programmers write a function, there is a
certain probability that they make a mistake in implementing the function
body. When programmers specify the result of the function in the postconditions,
there is also a certain probability that they make a mistake in writing
the contract. However, the probability that programmers make a mistake
twice (in both the body and the contract) is in
general lower than the probability that the mistake is made only once
(in either the body or the contract).
Easier testing: Contract programming facilitates testing because a contract
naturally specifies what a test should check. For example, preconditions
of a function state which inputs cause the function to fail and postconditions
state which outputs are produced by the function on successful exit (contract
programming should be seen as a tool to complement and guide, but obviously
not to replace, testing).
Formal design: Contract programming can serve to reduce the gap between
designers and programmers by providing a precise and unambiguous specification
language in terms of contract assertions. Moreover, contracts can make
code reviews easier by clarifying some of the semantics and usage of
the code.
Formalize inheritance: Contract programming formalizes the virtual function
overriding mechanism using subcontracting as justified by the substitution
principle. This keeps the base class programmers in control as
overriding functions always have to fully satisfy the contracts of their
base classes.
Replace defensive programming: Contract programming assertions can replace
defensive
programming checks localizing these checks within the contracts
and making the code more readable.
Of course, not all formal contract specifications can be asserted in C++.
For example, in C++ is it not possible to assert the validity of an iterator
range in the general case (because the only way to check if two iterators
form a valid range is to keep incrementing the first iterator until it reaches
the second iterator, but if the iterator range is invalid then such a code
would render undefined behaviour or run forever instead of failing an assertion).
Nevertheless, a large amount of contract assertions can be successfully programmed
in C++ as illustrated by the numerous examples in this documentation and
from the literature (for example see how much of STL vector contract assertions can actually
be programmed in C++ using this library).
Costs
In general, contract programming benefits come at the cost of performance
as discussed in detail by both [Stroustrup94]
and [Meyer97]. While performance trade-offs
should be carefully considered depending on the specific application domain,
software quality cannot be sacrificed: It is difficult to see value in software
that quickly and efficiently provides incorrect results.
The run-time performances are negatively impacted by contract programming
mainly because of extra time require to:
Check the asserted conditions.
Copy old values when these are used in postconditions or exception guarantees.
Call additional functors that check preconditions, postconditions, exception
guarantees, class invariants, etc. (these can add up to many extra calls
especially when using subcontracting).
In general, contracts introduce at least three extra functor calls to check
preconditions, postconditions, and exception guarantees for any given non-member
function call. Public functions introduce also two more function calls
to check class invariants (at entry and at exit). For subcontracting, these
extra calls (some of which become virtual calls) are repeated for the number
of functions being overridden from the base classes (possibly deep in the
inheritance tree). In addition to that, this library introduces a number
of function calls internal to its implementation in order to properly check
the contracts.
To mitigate the run-time performance impact, programmers can selectively
disable run-time checking of some of the contract assertions. Programmers
will have to decide based on the performance trade-offs required by their
specific applications, but a reasonable approach often is to (see Disable
Contract Checking):
Always write contracts to clarify the semantics of the design embedding
the specifications directly in the code and making the code self-documenting.
Check preconditions, postconditions, class invariants, and maybe even
exception guarantees during initial testing.
Check only preconditions (and maybe class invariants, but not postconditions
and exception guarantees) during release testing and for the final release.
This approach is usually reasonable because in well-tested production code,
validating the function body implementation using postconditions is rarely
needed since the function has shown itself to be correct during
testing. On the other hand, checking function arguments using preconditions
is always needed because of changes that can be made to the calling code
(without having to necessarily re-test and re-release the called code). Furthermore,
postconditions and also exception guarantees, with related old value copies,
are often computationally more expensive to check than preconditions and
class invariants.
Function
CallsNon-Member
Functions
A call to a non-member function with a contract executes the following steps
(see boost::contract::function):
Check function preconditions.
Execute the function body.
If the body did not throw an exception, check function postconditions.
Else, check function exception guarantees.
Private
and Protected Functions
Private and protected functions do not have to satisfy class invariants because
these functions are part of the class implementation and not of the class
public interface. Furthermore, the substitution
principle does not apply to private and protected functions because
these functions are not accessible to the user at the calling site where
the substitution
principle applies.
Therefore, calls to private and protected functions with contracts execute
the same steps as the ones indicated above for non-member functions (checking
only preconditions and postconditions, without checking class invariants
and without subcontracting).
Public
Function CallsOverriding
Public Functions
Let's consider a public function in a derived class that overrides public
virtual functions declared by its public base classes (because of C++ multiple
inheritance, the function could override from more than one of its base classes).
We refer to the function in the derived class as the overriding
function, and to the set of base classes containing all the overridden
functions as overridden bases.
When subcontracting, overridden functions are searched (at compile-time)
deeply in all public branches of the inheritance tree (i.e., not just the
derived class' direct public parents are inspected, but also all its public
grandparents, etc.). In case of multiple inheritance, this search also extends
(at compile-time) widely to all public trees of the multiple inheritance
forest (multiple public base classes are searched following their order of
declaration in the derived class' inheritance list). As usual with C++ multiple
inheritance, this search could result in multiple overridden functions and
therefore in subcontracting from multiple public base classes. Note that
only public base classes are considered for subcontracting because private
and protected base classes are not accessible to the user at the calling
site where the substitution
principle applies.
A call to the overriding public function with a contract executes the following
steps (see boost::contract::public_function):
Check static class invariants AND
non-static class invariants for all overridden bases, AND
then check the derived class static AND
non-static invariants.
Check preconditions of overridden public functions from all overridden
bases in OR
with each other, OR
else check the overriding function preconditions in the derived class.
Execute the overriding function body.
Check static class invariants AND
non-static class invariants for all overridden bases, AND
then check the derived class static AND
non-static invariants (even if the body threw an exception).
If the body did not throw an exception, check postconditions of overridden
public functions from all overridden bases in AND
with each other, AND
then check the overriding function postconditions in the derived class.
Else, check exception guarantees of overridden public functions from
all overridden bases in AND
with each other, AND
then check the overriding function exception guarantees in the derived
class.
Volatile public functions check static class invariants AND
volatile class invariants instead. Preconditions and postconditions of volatile
public functions and volatile class invariants access the object as volatile.
Class invariants are checked before preconditions and postconditions so programming
precondition and postcondition assertions can be simplified assuming that
class invariants are satisfied already (e.g., if class invariants assert
that a pointer cannot be null then preconditions and postconditions can safety
dereference that pointer without additional checking). Similarly, static
class invariants are checked before non-static class invariants so programming
non-static class invariant (volatile and non) can be simplified assuming
that static class invariants are satisfied already. Furthermore, subcontracting
checks contracts of public base classes before checking the derived class
contracts so programming derived class contract assertions can be simplified
by assuming that public base class contracts are satisfied already.
In this documentation
AND
and OR
indicate the logic and and or
operations evaluated in short-circuit. For example:
pANDq is true if and only if
both p and q are true, but q
is never evaluated when p
is false; pORq is true if and only if
either p or q are true, but q
is never evaluated when p
is true.
As indicated by the steps above and in accordance with the substitution
principle, subcontracting checks preconditions in OR
while class invariants, postconditions, and exceptions guarantees are checked
in AND
with preconditions, class invariants, postconditions, and exceptions guarantees
of base classes respectively.
Non-Overriding
Public Functions
A call to a non-static public function with a contract (that does not override
functions from any of its public base classes) executes the following steps
(see boost::contract::public_function):
Check class static AND
non-static invariants (but none of the invariants from base classes).
Check function preconditions (but none of the preconditions from functions
in base classes).
Execute the function body.
Check the class static AND
non-static invariants (even if the body threw an exception, but none
of the invariants from base classes).
If the body did not throw an exception, check function postconditions
(but none of the postconditions from functions in base classes).
Else, check function exception guarantees (but none of the exception
guarantees from functions in base classes).
Volatile public functions check static class invariants AND
volatile class invariants instead. Preconditions and postconditions of volatile
functions and volatile class invariants access the object as volatile.
Class invariants are checked because this function is part of the class public
interface. However, none of the contracts of the base classes are checked
because this function does not override any functions from any of the public
base classes (so the substitution
principle does not require to subcontract in this case).
Static
Public Functions
A call to a static public function with a contract executes the following
steps (see boost::contract::public_function):
Check static class invariants (but not the non-static invariants and
none of the invariants from base classes).
Check function preconditions (but none of the preconditions from functions
in base classes).
Execute the function body.
Check static class invariants (even if the body threw an exception, but
not the non-static invariants and none of the invariants from base classes).
If the body did not throw an exception, check function postconditions
(but none of the postconditions from functions in base classes).
Else, check function exception guarantees (but none of the exception
guarantees from functions in base classes).
Class invariants are checked because this function is part of the class public
interface, but only static class invariants can be checked (because this
is a static function so it cannot access the object that would instead be
required to check non-static class invariants, volatile or not). Furthermore,
static functions cannot override any function so the substitution
principle does not apply and they do not subcontract.
Preconditions and postconditions of static functions and static class invariants
cannot access the object (because they are checked from static
member functions).
Constructor
Calls
A call to a constructor with a contract executes the following steps (see
boost::contract::constructor_precondition
and boost::contract::constructor):
Check constructor preconditions (but these cannot access the object because
the object is not constructed yet).
Execute the constructor member initialization list (if present).
Construct any base class (public or not) according with C++ construction
mechanism and also check the contracts of these base constructors
(according with steps similar to the ones listed here).
Check static class invariants (but not the non-static or volatile class
invariants, because the object is not constructed yet).
Execute the constructor body.
Check static class invariants (even if the body threw an exception).
If the body did not throw an exception:
Check non-static AND
volatile class invariants (because the object is now successfully
constructed).
Check constructor postconditions (but these cannot access the object
old value oldof(*this) because the object was not constructed
before the execution of the constructor body).
Else, check constructor exception guarantees (but these cannot access
the object old value oldof(*this) because the object was not constructed
before the execution of the constructor body, plus they can only access
class' static members because the object has not been successfully constructed
given the constructor body threw an exception in this case).
Constructor preconditions are checked before executing the member initialization
list so programming these initializations can be simplified assuming the
constructor preconditions are satisfied (e.g., constructor arguments can
be validated by the constructor preconditions before they are used to initialize
base classes and data members).
As indicated in step 2.a. above, C++ object construction mechanism will automatically
check base class contracts when these bases are initialized (no explicit
subcontracting behaviour is required here).
Destructor
Calls
A call to a destructor with a contract executes the following steps (see
boost::contract::destructor):
Check static class invariants AND
non-static AND
volatile class invariants.
Execute the destructor body (destructors have no parameters and they
can be called at any time after object construction so they have no preconditions).
Check static class invariants (even if the body threw an exception).
If the body did not throw an exception:
Check destructor postconditions (but these can only access class'
static members and the object old value oldof(*this) because the object has been destroyed
after successful execution of the destructor body). Rationale: Postconditions for
destructors are not part of [N1962]
or other references listed in the Bibliography
(but with respect to [Meyer97]
it should be noted that Eiffel does not support static data members
and that might by why destructors do not have postconditions
in Eiffel). However, in principle there could be uses for destructor
postconditions so this library supports postconditions for destructors
(e.g., a class that counts object instances could use destructor
postconditions to assert that an instance counter stored in a
static data member is decreased by 1
because the object has been destructed).
Destroy any base class (public or not) according with C++ destruction
mechanism and also check the contracts of these base destructors
(according with steps similar to the ones listed here).
Else (even if destructors should rarely, if ever, be allowed to throw
exceptions in C++):
Check non-static AND
volatile class invariants (because the object was not successfully
destructed so it still exists and should satisfy its invariants).
Check destructor exception guarantees.
As indicated in step 4.b. above, C++ object destruction mechanism will automatically
check base class contracts when the destructor exits without throwing an
exception (no explicit subcontracting behaviour is required here).
Given that C++ allows destructors to throw, this library handles the case
when the destructor body throws an exception as indicated above. However,
in order to comply with STL exception safety guarantees and good C++ programming
practices, programmers should implement destructor bodies to rarely, if
ever, throw exceptions (in fact destructors are implicitly declared noexcept in C++11).
Constant-Correctness
Contracts should not be allowed to modify the program state because they
are only responsible to check (and not to change) the program state in order
to verify its compliance with the specifications. Therefore, contracts should
only access objects, function arguments, function return values, old values,
and all other program variables in const
context (via const&,
const*const, constvolatile, etc.).
Whenever possible (e.g., class invariants and postcondition old values),
this library automatically enforces this constant-correctness constraint
at compile-time using const.
However, this library cannot automatically enforce this constraint in all
cases (for preconditions and postconditions of mutable member functions,
for global variables, etc.). See No
Lambda Functions for ways of using this library that enforce the constant-correctness
constraint at compile-time (but at the cost of significant boiler-plate code
to be programmed manually so not recommended in general).
In general, it is the responsibility of the programmers to code assertions
that only check, and do not change, program variables.
Note that this is true when using C-style assert
as well.
Specifications
vs. Implementation
Contracts are part of the program specification and not of its implementation.
Therefore, contracts should ideally be programmed within C++ declarations,
and not within definitions.
In general, this library cannot satisfy this requirement. However, even when
contracts are programmed together with the body in the function definition,
it is still fairly easy for users to identify and read just the contract
portion of the function definition (because the contract code must always
be programmed at the very top of the function definition). See Separate
Body Implementation for ways of using this library to program contract
specifications outside of the body implementation (but at the cost of writing
one extra function for any given function so not recommended in general).
Furthermore, contracts are most useful when they assert conditions only using
public members (in most cases, the need for using non-public members to check
contracts, especially in preconditions, indicates an error in the class design).
For example, the caller of a public function cannot in general make sure
that the function preconditions are satisfied if the precondition assertions
use private members that are not callable by the caller (therefore, a failure
in the preconditions will not necessarily indicate a bug in the caller given
that the caller was made unable to fully check the preconditions in the first
place). However, given that C++ provides programmers ways around access level
restrictions (friend, function
pointers, etc.), this library leaves it up to programmers to make sure that
only public members are used in contract assertions (especially in preconditions).
([N1962] follows the same approach not
restricting contracts to only use public members, Eiffel instead generates
a compile-time error if preconditions are asserted using non-public members.)
Rationale: Out of curiosity, if C++ defect
45 had not been fixed, this library could have been implemented
to generate a compile-time error when precondition assertions use non-public
members more similarly to Eiffel's implementation (but still, not necessary
the best approach for C++).
On
Contract Failures
If preconditions, postconditions, exception guarantees, or class invariants
are either checked to be false or their evaluation throws an exception at
run-time then this library will call specific failure handler functions.
Rationale: If the evaluation of a contract
assertion throws an exception, the assertion cannot be checked to be true
so the only safe thing to assume is that the assertion failed (indeed the
contract assertion checking failed) and call the contract failure handler
in this case also.
By default, these failure handler functions print a message to the standard
error std::cerr (with detailed information about the
failure) and then terminate the program calling std::terminate.
However, using boost::contract::set_precondition_failure,
boost::contract::set_postcondition_failure,
boost::contract::set_except_failure,
boost::contract::set_invariant_failure,
etc. programmers can define their own failure handler functions that can
take any user-specified action (throw an exception, exit the program with
an error code, etc., see Throw
on Failures). Rationale: This customizable failure handling
mechanism is similar to the one used by C++ std::terminate
and also to the one proposed in [N1962].
In C++ there are a number of issues with programming contract failure handlers
that throw exceptions instead of terminating the program. Specifically,
destructors check class invariants so they will throw if programmers change
class invariant failure handlers to throw instead of terminating the program,
but in general destructors should not throw in C++ (to comply with STL
exception safety, C++11 implicit noexcept
declarations for destructors, etc.). Furthermore, programming a failure
handler that throws on exception guarantee failures results in throwing
an exception (the one reporting the contract failure) while there is already
an active exception (the one that caused the exception guarantees to be
checked in the first place), and this will force C++ to terminate the program
anyway.
Therefore, it is recommended to terminate the program at least for contract
failures from destructors and exception guarantees (if not in all other cases
of contract failures as it is done by default by this library). The contract
failure handler functions programmed using this library have information
about the failed contract (preconditions, postconditions, etc.) and the operation
that was checking the contract (constructor, destructor, etc.) so programmers
can granularly distinguish all cases and decide when it is appropriate to
terminate, throw, or take some other user-specific action.
Feature
Summary
The contract programming features supported by this library are largely based
on [N1962] and on the Eiffel programming
language.
The following table compares contract programming features among this library,
[N1962] (unfortunately the C++ standard
committee rejected this proposal commenting on a lack of interest in adding
contract programming to C++ at that time, even if [N1962]
itself is sound), a more recent proposal [P0380]
(which was accepted in the C++20 standard but unfortunately only supports
preconditions and postconditions, while does not support class invariants,
old values, and subcontracting), the Eiffel and D programming languages.
Some of the items listed in this summary table will become clear in detail
after reading the remaining sections of this documentation.
Feature
This Library
[N1962] Proposal (not accepted
in C++)
C++20 (see [P0380])
ISE Eiffel 5.4 (see [Meyer97])
D (see [Bright04])
Keywords and specifiers
Specifiers: precondition,
postcondition,
invariant, static_invariant, and base_types. The last three specifiers
appear in user code so their names can be referred to or changed
using BOOST_CONTRACT_INVARIANT,
BOOST_CONTRACT_STATIC_INVARIANT,
and BOOST_CONTRACT_BASES_TYPEDEF
macros respectively to avoid name clashes.
Keywords: precondition,
postcondition,
oldof, and invariant.
Attributes: [[expects]] and [[ensures]].
Keywords: require, require else,
ensure, ensure then, old,
result, do, and invariant.
Keywords: in, out, do,
assert, and invariant.
On contract failures
Print an error to std::cerr
and call std::terminate (but can be customized
to throw exceptions, exit with an error code, etc.).
Call std::terminate (but can be customized
to throw exceptions, exit with an error code, etc.).
Call std::abort (but can be customized
to throw exceptions, exit with an error code, etc.).
Throw exceptions.
Throw exceptions.
Return values in postconditions
Yes, captured by or passed as a parameter to (for virtual functions)
the postcondition functor.
Yes, postcondition(result-variable-name).
Yes, [[ensuresresult-variable-name:...]].
Yes, result keyword.
Yes, out(result-variable-name).
Old values in postconditions
Yes, BOOST_CONTRACT_OLDOF
macro and boost::contract::old_ptr
(but copied before preconditions unless .old(...)
is used as shown in Old
Values Copied at Body). For templates, boost::contract::old_ptr_if_copyable
skips old value copies for non-copyable types and boost::contract::condition_if
skips old value copies selectively based on old expression type
requirements (on compilers that do not support ifconstexpr).
Yes, oldof keyword
(copied right after preconditions). (Never skipped, not even in
templates for non-copyable types.)
No.
Yes, old keyword (copied right after preconditions).
(Never skipped, but all types are copyable in Eiffel.)
No.
Class invariants
Yes, checked at constructor exit, at destructor entry and throw,
and at public function entry, exit, and throw. Same for volatile
class invariants. Static class invariants checked at entry, exit,
and throw for constructors, destructors, and any (also static) public function.
Yes, checked at constructor exit, at destructor entry and throw,
and at public function entry, exit, and throw. (Volatile and static
class invariants not supported.)
No.
Yes, checked at constructor exit, and around public functions.
(Volatile and static class invariants do not apply to Eiffel.)
Yes, checked at constructor exit, at destructor entry, and around
public functions. However, invariants cannot call public functions
(to avoid infinite recursion because D does not disable contracts
while checking other contracts). (Volatile and static class invariants
not supported, volatile
was deprecated all together in D.)
Subcontracting
Yes, also supports subcontracting for multiple inheritance (BOOST_CONTRACT_BASE_TYPES,
BOOST_CONTRACT_OVERRIDE,
and boost::contract::virtual_
are used to declare base classes, overrides and virtual public
functions respectively).
Yes, also supports subcontracting for multiple inheritance, but
preconditions cannot be subcontracted. Rationale: The authors of [N1962] decided to forbid derived
classes from subcontracting preconditions because they found
that such a feature was rarely, if ever, used (see Re:
[boost] [contract] diff n1962). Still, it should be noted
that even in [N1962] if a
derived class overrides two functions with preconditions coming
from two different base classes via multiple inheritance, the
overriding function contract will check preconditions from its
two base class functions in OR
(so even in [N1962] preconditions
can indirectly subcontract when multiple inheritance is used).
Furthermore, subcontracting preconditions is soundly defined
by the substitution
principle so this library allows to subcontract preconditions
as Eiffel does (users can always avoid using this feature if
they have no need for it). (This is essentially the only feature
on which this library deliberately differs from [N1962].)
No.
Yes.
Yes.
Contracts for pure virtual functions
Yes (programmed via out-of-line functions as always in C++ with
pure virtual function definitions).
Yes.
No (because no subcontracting).
Yes (contracts for abstract functions).
No.
Arbitrary code in contracts
Yes (but users are generally recommended to only program assertions
using BOOST_CONTRACT_ASSERT
and if-guard statements within contracts to avoid introducing bugs
and expensive code in contracts, and also to only use public functions
to program preconditions).
No, assertions only (use of only public functions to program preconditions
is recommended but not prescribed).
No, assertions only (in addition contracts of public, protected,
and private members can only use other public, public/protected,
and public/protected/private members respectively).
No, assertions only (in addition only public members can be used
in preconditions).
Yes.
Constant-correctness
No, enforced only for class invariants and old values (making also
preconditions and postconditions constant-correct is possible but
requires users to program a fare amount of boiler-plate code).
Yes.
Yes (side effects in contracts lead to undefined behaviour).
Yes.
No, enforced only for class invariants.
Contracts in specifications
No, in function definitions instead (unless programmers manually
write an extra function for any given function).
Yes (in function declarations).
Yes (in function declarations).
Yes.
Yes.
Function code ordering
Preconditions, postconditions, exception guarantees, body.
Preconditions, postconditions, body.
Preconditions, postconditions, body.
Preconditions, body, postconditions.
Preconditions, postconditions, body.
Disable assertion checking within assertions checking
(to avoid infinite recursion when checking contracts)
Yes, but use BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
to disable no assertion while checking preconditions (see also
BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION).
Rationale: Technically, it can
be shown that an invalid argument can reach the function body
when assertion checking is disabled while checking preconditions
(that is why [N1962] does
not disable any assertion while checking preconditions, see
Re:
[boost] [contract] diff n1962). However, this can only
happen while checking contracts when an invalid argument passed
to the body, which should results in the body either throwing
an exception or returning an incorrect result, will in turn fail
the contract assertion being checked by the caller of the body
and invoke the related contract failure handler as desired in
the first place. Furthermore, not disabling assertions while
checking preconditions (like [N1962]
does) makes it possible to have infinite recursion while checking
preconditions. Therefore, this library by default disables assertion
checking also while checking preconditions (like Eiffel does),
but it also provides the BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
configuration macro so users can change this behaviour to match
[N1962] if needed.
(In multi-threaded programs this introduces a global
lock, see BOOST_CONTRACT_DISABLE_THREADS.)
Yes for class invariants and postconditions, but preconditions
disable no assertion.
No.
Yes.
No.
Nested member function calls
Disable nothing. Rationale: Older versions of
this library defined a data member in the user class that was
automatically used to disable checking of class invariants within
nested member function calls (similarly to Eiffel). This feature
was required by older revisions of [N1962]
but it is no longer required by [N1962]
(because it seems to be motivated purely by optimization reasons
while similar performances can be achieved by disabling invariants
for release builds). Furthermore, in multi-threaded programs
this feature would introduce a lock that synchronizes all member
functions calls for a given object. Therefore, this feature was
removed in the current revision of this library.
Disable nothing.
Disable nothing.
Disable all contract assertions.
Disable nothing.
Disable contract checking
Yes, contract checking can be skipped at run-time by defining combinations
of the BOOST_CONTRACT_NO_PRECONDITIONS,
BOOST_CONTRACT_NO_POSTCONDITIONS,
BOOST_CONTRACT_NO_INVARIANTS,
BOOST_CONTRACT_NO_ENTRY_INVARIANTS,
and BOOST_CONTRACT_NO_EXIT_INVARIANTS
macros (completely removing contract code from compiled object
code is also possible but requires using macros as shown in Disable
Contract Compilation).
Yes (contract code also removed from compiled object code, but
details are compiler-implementation specific).
Yes (contract code also removed from compiled object code, but
details are compiler-implementation specific).
Yes, but only predefined combinations of preconditions, postconditions,
and class invariants can be disabled (contract code also removed
from compiled object code).
Yes.
Assertion levels
Yes, predefined default, audit, and axiom, in addition programmers
can also define their own levels.
No (but a previous revision of this proposal considered adding
assertion levels under the name of "assertion ordering").
Yes, predefined default, audit, and axiom.
No.
No.
The authors of this library consulted the following references that implement
contract programming for C++ (but usually for only a limited set of features,
or using preprocessing tools other than the C++ preprocessor and external
to the language itself) and for other languages (see Bibliography
for a complete list of all references consulted during the design and development
of this library):
Reference
Language
Notes
[Bright04b]
Digital Mars C++
The Digital Mars C++ compiler extends C++ adding contract programming
language support (among many other features).
[Maley99]
C++
This supports contract programming including subcontracting but
with limitations (e.g., programmers need to manually build an inheritance
tree using artificial template parameters), it does not use macros
but programmers are required to write by hand a significant amount
of boiler-plate code. (The authors have found this work very inspiring
when developing initial revisions of this library especially for
its attempt to support subcontracting.)
[Lindrud04]
C++
This supports class invariants and old values but it does not support
subcontracting (contracts are specified within definitions instead
of declarations and assertions are not constant-correct).
[Tandin04]
C++
Interestingly, these contract macros automatically generate Doxygen
documentation Rationale: Older versions of
this library also automatically generated Doxygen documentation
from contract definition macros. This functionality was abandoned
for a number of reasons: This library no longer uses macros to
program contracts; even before that, the implementation of this
library macros became too complex and the Doxygen preprocessor
was no longer able to expand them; the Doxygen documentation
was just a repeat of the contract code (so programmers could
directly look at contracts in the source code); Doxygen might
not necessarily be the documentation tool used by all C++ programmers.
but old values, class invariants, and subcontracting
are not supported (plus contracts are specified within definitions
instead of declarations and assertions are not constant-correct).
[Nana]
GCC C++
This uses macros but it only works on GCC (and maybe Clang, but
it does not work on MSVC, etc.). It does not support subcontracting.
It requires extra care to program postconditions for functions
with multiple return statements. It seems that it might not check
class invariants when functions throw exceptions (unless the END macro does that...). (In
addition, it provides tools for logging and integration with GDB.)
[C2]
C++
This uses an external preprocessing tool (the authors could no
longer find this project's code to evaluate it).
[iContract]
Java
This uses an external preprocessing tool.
[Jcontract]
Java
This uses an external preprocessing tool.
[CodeContracts]
.NET
Microsoft contract programming for .NET programming languages.
[SpecSharp]
C#
This is a C# extension with contract programming language support.
[Chrome]
Object Pascal
This is the .NET version of Object Pascal and it has language support
for contract programming.
[SPARKAda]
Ada
This is an Ada-like programming language with support for contract
programming.
To the best knowledge of the authors, this the only library that fully supports
all contract programming features for C++ (without using preprocessing tools
external to the language itself). In general:
Implementing preconditions and postconditions in C++ is not difficult
(e.g., using some kind of RAII object).
Implementing postcondition old values is also not too difficult (usually
requiring programmers to copy old values into local variables), but it
is already somewhat more difficult to ensure such copies are not performed
when postconditions are disabled.
For example, the following pseudocode attempts to emulate old values
in [P0380]:
structscope_exit{// RAII.template<typenameF>explicitscope_exit(Ff):f_(f){}~scope_exit(){f_();}scope_exit(scope_exitconst&)=delete;scope_exit&operator=(scope_exitconst&)=delete;private:std::function<void()>f_;};voidfswap(file&x,file&y)[[expects:x.closed()]][[expects:y.closed()]]// Cannot use [[ensures]] for postconditions so to emulate old values.{fileold_x=x;// Emulate old values with local copies (not disabled).fileold_y=y;scope_exitensures([&]{// Check after local objects destroyed.if(std::uncaught_exceptions()==0){// Check only if no throw.[[assert:x.closed()]][[assert:y.closed()]][[assert:x==old_y]][[assert:y==old_x]]}});x.open();scope_exitclose_x([&]{x.close();});y.open();scope_exitclose_y([&]{y.close();});filez=file::temp();z.open;scope_exitclose_z([&]{z.close();});x.mv(z);y.mv(x);z.mv(y);}
This requires boiler-plate code to make sure postconditions are correctly
checked only if the function did not throw an exception and in a scope_exit RAII object after all
other local objects have been destroyed (because some of these destructors
contribute to establishing the postconditions). Still, it never disables
old value copies (not even if postconditions are disabled in release
builds, this would require adding even more boiler-plate code using
#ifdef, etc.).
Implementing class invariants is more involved (especially if done automatically,
without requiring programmers to manually invoke extra functions to check
the invariants).
For example, the following pseudocode attempts to emulation of class
invariants in [P0380]:
template<typenameT>classvector{boolinvariant()const{// Check invariants at...[[assert:empty()==(size()==0)]][[assert:size()<=capacity()]]returntrue;}public:vector()[[ensures:invariant()]]// ...constructor exit (only if no throw).{...}~vector()noexcept[[expects:invariant()]]// ...destructor entry.{...}voidpush_back(Tconst&value)[[expects:invariant()]]// ...public function entry.[[ensures:invariant()]]// ...public function exit (if no throw).try{...// Function body.}catch(...){invariant();// ...public function exit (if throw).throw;}...};
This requires boiler-plate code to manually invoke the function that
checks the invariants (note that invariants are checked at public function
exit regardless of exceptions being thrown while postconditions are
not). In case the destructor can throw (e.g., it is declared noexcept(false)),
the destructor also requires a try-catch
statement similar to the one programmed for push_back
to check class invariants at destructor exit when it throws exceptions.
Still, an outstanding issue remains to avoid infinite recursion if
also empty and size are public functions programmed
to check class invariants (because [P0380]
does not automatically disable assertions while checking other assertions).
In addition, all references reviewed by the authors seem
to not consider static and volatile functions not supporting static and
volatile invariants respectively.
Implementing subcontracting involves a significant amount of complexity
and it seems to not be properly supported by any C++ library other than
this one (especially when handling multiple inheritance, correctly copying
postcondition old values across all overridden contracts deep in the
inheritance tree, and correctly reporting the return value to the postconditions
of overridden virtual functions in base classes).
For example, it is not really possible to sketch pseudocode based on
[P0380] that emulates subcontracting
in the general case.
Tutorial
This section is a guide to basic usage of this library.
Non-Member
Functions
Contracts for non-member functions are programmed using boost::contract::function.
For example (see non_member.cpp):
#include<boost/contract.hpp>// Contract for a non-member function.intinc(int&x){intresult;boost::contract::old_ptr<int>old_x=BOOST_CONTRACT_OLDOF(x);boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(x<std::numeric_limits<int>::max());}).postcondition([&]{BOOST_CONTRACT_ASSERT(x==*old_x+1);BOOST_CONTRACT_ASSERT(result==*old_x);}).except([&]{BOOST_CONTRACT_ASSERT(x==*old_x);});returnresult=x++;// Function body.}
All necessary header files of this library are included by #include<boost/contract.hpp>.
Alternatively, programmers can selectively include only the header files
they actually need among boost/contract/*.hpp (see Getting Started).
It is possible to specify preconditions, postconditions, and exception guarantees
for non-member functions (see Preconditions,
Postconditions,
and Exception
Guarantees).
The boost::contract::function
function returns an RAII object that must always be assigned to a local variable
of type boost::contract::check
(otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL).
The name of this local variable is arbitrary, but c
is often used in this documentation for check or caminiti
;-) .
Furthermore, C++11 auto
declarations cannot be used here and the boost::contract::check
type must be explicitly specified (otherwise this library will generate a
compile-time error prior C++17 and a run-time error post C++17). Rationale: C++17 guaranteed copy elision
on function return value voids the trick this library uses to force a compile-time
error when auto is incorrectly
used instead of boost::contract::check.
The library still generates a run-time error in this case (also on C++17).
In any case, after reading this documentation it should be evident to programmers
that auto should not be used
in boost::contract::check
declarations so this misuse of auto
should not be an issue in practice.
The function body is programmed right after the declaration of
this RAII object.
In some cases, it might be necessary to program some code before the contract.
For example for acquiring resources that will be used while checking the
contract like old values, but also to lock mutexes (or other synchronization
mechanisms) in multi-threaded programs.
At construction, the boost::contract::check
RAII object for non-member functions does the following (enclosing function
entry):
Check preconditions, by calling the nullary functor r() passed to .precondition(r).
At destruction instead (enclosing function exit):
If the function body did not throw an exception:
Check postconditions, by calling the nullary functor s() passed to .postcondition(s).
Else:
Check exception guarantees, by calling the nullary functor e() passed to .except(e).
This ensures that non-member function contracts are correctly checked at
run-time (see Function
Calls). (Also note that functions will correctly check their contracts
even when they are called via function pointers, function objects, etc.)
A non-member function can avoid calling boost::contract::function
for efficiency but only when it has no preconditions, no postconditions,
and no exception guarantees.
Preconditions
When preconditions are specified, they are programmed using a functor r
passed to .precondition(r) that can be called with no parameters as
in r().
Contracts that do not have preconditions simply do not call .precondition(...). Preconditions must appear before postconditions
and exception guarantees when these are all present (see Postconditions
and Exception
Guarantees).
C++11 lambda functions are convenient to program preconditions, but any other
nullary functor can be used (see No
Lambda Functions).
Lambda functions with no parameters can be programmed in C++11 as [...](){...}
but also equivalently as [...]{...}.
This second from is often used in this documentation omitting the empty
parameter list () for brevity.
For example, for boost::contract::function
(similarly for public functions, instead destructors do not have preconditions
and constructors use boost::contract::constructor_precondition,
see Public Functions,
Destructors, and
Constructors):
voidf(...){boost::contract::checkc=boost::contract::function()// Same for all other contracts..precondition([&]{// Capture by reference or value...BOOST_CONTRACT_ASSERT(...);// ...and should not modify captures....})...;...}
The precondition functor should capture all the variables that it needs to
assert the preconditions. These variables can be captured by value when the
overhead of copying such variables is acceptable.
In this documentation preconditions often capture variables by reference
to avoid extra copies.
In any case, programmers should not write precondition assertions
that modify the value of the captured variables, even when those are captured
by reference (see Constant-Correctness).
Any code can be programmed in the precondition functor, but it is recommended
to keep this code simple using mainly assertions and if-statements (to avoid
programming complex preconditions that might be buggy and also slow to check
at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT
to program precondition assertions because that enables this library to print
informative error messages when the asserted conditions are evaluated to
be false (note that this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` contains commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call the failure handler boost::contract::precondition_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if calling the functor specified
via .precondition(...) throws any exception. By default, this
failure handler prints an error message to std::cerr
and terminates the program calling std::terminate
(see Throw
on Failures to change the failure handler to throw exceptions, exit
the program with an error code, etc.).
Contracts are most useful when their assertions only use public members
that are accessible to the caller so the caller can properly check and
use the contract. In particular, preconditions of a public function or
constructor that use non-public members are essentially incorrect because
they cannot be fully checked by the caller (in fact, Eiffel generates a
compile-time error in this case). However, this library does not enforce
such a constraint and it leaves it up to programmers to only use public
members when programming contracts, especially when asserting preconditions
(see Specifications
vs. Implementation).
Postconditions
When postconditions are specified, they are programmed using a functor s
passed to .postcondition(s) that can be called with no parameters as
in s().
Contracts that do not have postconditions simply do not call .postcondition(...). Postconditions must appear after preconditions
but before exception guarantees when these are all present (see Preconditions
and Exception
Guarantees).
C++11 lambda functions are convenient to program postconditions, but any
other nullary functor can be used (see No
Lambda Functions). For example, for boost::contract::function
(similarly for all other contracts):
voidf(...){boost::contract::checkc=boost::contract::function()// Same for all other contracts.....postcondition([&]{// Capture by reference...BOOST_CONTRACT_ASSERT(...);// ...but should not modify captures....})...;...}
The postcondition functor should capture all the variables that it needs
to assert the postconditions. In general, these variables should be captured
by reference and not by value (because postconditions need to access the
value that these variables will have at function exit, and not the value
these variables had when the postcondition functor was first declared). Postconditions
can also capture return and old values (see Return
Values and Old
Values). In any case, programmers should not write postcondition assertions
that modify the value of the captured variables, even when those are captured
by reference (see Constant-Correctness).
Any code can be programmed in the postcondition functor, but it is recommended
to keep this code simple using mainly assertions and if-statements (to avoid
programming complex postconditions that might be buggy and slow to check
at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT
to program postcondition assertions because that enables this library to
print informative error messages when the asserted conditions are evaluated
to be false (note that this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` has commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call the failure handler boost::contract::postcondition_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if calling the functor specified
via .postcondition(...) throws any exception. By default, this
failure handler prints an error message to std::cerr
and terminates the program calling std::terminate
(see Throw
on Failures to change the failure handler to throw exceptions, exit
the program with an error code, etc.).
For non-void virtual public functions and non-void public function overrides,
the functor s passed to .postcondition(s) is not a nullary functor, instead it is
a unary functor taking a variable holding the return value as its one parameter
s(result) (this is to properly support subcontracting,
see Virtual
Public Functions and Public
Function Overrides).
Return Values
In non-void functions, postconditions might need to access the function return
value to program assertions. In these cases, programmers are responsible
to declare a local variable before the contract and to assign it to the return
value at function exit (when the function does not throw an exception).
The name of the local variable that holds the return value is arbitrary,
but result is often used
in this documentation.
For example, for boost::contract::function
(similarly for all other contracts):
return_typef(...){return_typeresult;// Must be later assigned to return value.boost::contract::checkc=boost::contract::function()// Same for all other contracts.....postcondition([&]{// Also capture `result` reference...BOOST_CONTRACT_ASSERT(result==...);// ...but should not modify captures....})...;...returnresult=...;// Assign `result` at each return.}
At any point where the enclosing function returns, programmers are responsible
to assign the result variable to the expression being returned. This can
be done ensuring that allreturn
statements in the function are of the form:
return-typeresult;...returnresult=return-expression;// Assign `result` at each return.
The functor used to program postconditions should capture the result variable
by reference and not by value (because postconditions must access the value
the result variable will have at function exit, and not the value the result
variable had when the postcondition functor was first declared). The return
value should never be used in preconditions, old value copies, or exception
guarantees (because the return value is not yet correctly evaluated and set
when preconditions are checked, old values are copied, or if the function
throws an exception). In any case, programmers should not modify the result
variable in the contract assertions (see Constant-Correctness).
It is also possible to declared the result variable using boost::optional
when the function return type does not have a default constructor, or if
the default constructor is too expensive or undesirable to execute when first
declaring the result variable (see Optional
Return Values).
Non-void virtual public functions and non-void public function overrides
must always declare and use a result variable even when postconditions do
not directly use the function return value (this is to properly support subcontracting,
see Virtual
Public Functions and Public
Function Overrides).
Old Values
When old values are used in postconditions or in exception guarantees, programmes
are responsible to declare local variables before the contract and to assign
them to related old value expressions using BOOST_CONTRACT_OLDOF.
The name of a local variable that holds an old value is arbitrary, but
old_variable-name is often used
in this documentation.
For example, for boost::contract::function
(similarly for all other contracts):
voidf(...){boost::contract::old_ptr<old_type>old_var=BOOST_CONTRACT_OLDOF(old_expr);...// More old value declarations here if needed.boost::contract::checkc=boost::contract::function()// Same for all other contracts....// Preconditions shall not use old values..postcondition([&]{// Capture by reference...BOOST_CONTRACT_ASSERT(*old_var==...);// ...but should not modify captures....}).except([&]{// Capture by reference...BOOST_CONTRACT_ASSERT(old_var->...);// ...but should not modify captures....});...}
Old values are handled by this library using the smart pointer class template
boost::contract::old_ptr
(so programmers do not directly manage allocation and deallocation of the
pointed memory). Rationale: Old values have to be optional
values because they need to be left uninitialized when they are not used
because both postconditions and exception guarantees are disabled (defining
BOOST_CONTRACT_NO_POSTCONDITIONS
and BOOST_CONTRACT_NO_EXCEPTS).
That is to avoid old value copies when old values are not used, either
a pointer or (better) a boost::optional
could have been used to achieve that. In addition, old values need to be
pointers internally allocated by this library so that they are never copied
twice even when calling an overridden function multiple times to check
preconditions, postconditions, etc. to implement subcontracting, so a smart
pointer class template was used.
The pointed old value type is automatically qualified as const (so old values cannot be mistakenly
changed by contract assertions, see Constant-Correctness).
This library ensures that old value pointers are always not null by the time
postconditions and exception guarantees are checked (so programmers can safely
dereference and use these pointers in postcondition and exception guarantee
assertions using operator*
and operator->
without having to check if old value pointers are not null first).
Old values should not be used in preconditions and this library does not
guarantee that old value pointers are always not null when preconditions
are checked.
For example, old value pointers might be null in preconditions when postconditions
and exception guarantees are disabled defining BOOST_CONTRACT_NO_POSTCONDITIONS
and BOOST_CONTRACT_NO_EXCEPTS
(but also when checking an overridden virtual public function contract
via subcontracting, etc.).
See Old
Values Copied at Body for delaying the copy of old values until after
class invariants (for constructors, destructors, and public functions) and
preconditions are checked (when necessary, this allows to program old value
expressions under the simplifying assumption that class invariant and precondition
assertions are satisfied already).
BOOST_CONTRACT_OLDOF is
a variadic macro and it takes an extra parameter when used in virtual public
functions or public function overrides (see Virtual
Public Functions and Public
Function Overrides). C++11 auto declarations can be used with BOOST_CONTRACT_OLDOF for brevity
autoold_variable-name
= BOOST_CONTRACT_OLDOF(expression) (but see
also Old
Value Requirements). See No
Macros to program old values without using BOOST_CONTRACT_OLDOF
(e.g., on compilers that do not support variadic macros).
This library ensures that old values are copied only once. This library
also ensures that old values are never copied when postconditions and exception
guarantees are disabled defining both BOOST_CONTRACT_NO_POSTCONDITIONS
and BOOST_CONTRACT_NO_EXCEPTS
(note that both these two macros must be defined, defining only BOOST_CONTRACT_NO_POSTCONDITIONS
or only BOOST_CONTRACT_NO_EXCEPTS
is not sufficient to prevent the run-time cost of old value copies).
Exception
Guarantees
When exception guarantees are specified, they are programmed using a functor
e passed to .except(e) that can be called with no parameters as
in e().
Contracts that do not have exception guarantees simply do not call .except(...). Exception guarantees must appear after
both preconditions and postconditions when these are all present (see Preconditions and
Postconditions).
C++11 lambda functions are convenient to program exception guarantees, but
any other nullary functor can be used (see No
Lambda Functions). For example, for boost::contract::function
(similarly for all other contracts):
voidf(...){boost::contract::checkc=boost::contract::function()// Same for all other contracts.....except([&]{// Capture by reference...BOOST_CONTRACT_ASSERT(...);// ...but should not modify captures....});...}
The exception guarantee functor should capture all the variables that it
needs to assert the exception guarantees. In general, these variables should
be captured by reference and not by value (because exception guarantees need
to access the value that these variables will have when the function throws,
and not the value these variables had when the exception guarantee functor
was first declared). Exception guarantees can also capture old values (see
Old Values) but
they should not access the function return value instead (because the return
value is not be properly set when the function throws an exception). In any
case, programmers should not write exception guarantee assertions that modify
the value of the captured variables, even when those are captured by reference
(see Constant-Correctness).
In real production code, it might be difficult to program meaningful exception
guarantees without resorting to expensive old value copies that will slow
down execution. Therefore, the authors recognize that exception guarantees,
even if supported by this library, might not be used often in practice
(and they are not used in most of the examples listed in the rest of this
documentation). In any case, these performance considerations are ultimately
left to programmers and their specific application domains.
Any code can be programmed in the exception guarantee functor, but it is
recommended to keep this code simple using mainly assertions and if-statements
(to avoid programming complex exception guarantees that might be buggy and
slow to check at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT
to program exception guarantee assertions because that enables this library
to print informative error messages when the asserted conditions are evaluated
to be false (note that this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` has commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call the failure handler boost::contract::except_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if calling the functor specified
via .except(...) throws any exception. By default, this
failure handler prints an error message to std::cerr
and terminates the program calling std::terminate
(see Throw
on Failures to change the failure handler to exit the program with
an error code or to take some other custom action).
While it is technically possible for programmers to specify an exception
guarantee handler that throws an exception in case of an exception guarantee
failure, this will force C++ to terminate the program. That is because
the handler will throw an exception while there is already an active exception
on the stack (the exception thrown by the function body that caused the
exception guarantees to be checked in the first place). Therefore, programmers
should not change the exception guarantee failure handler to throw exceptions.
Class Invariants
Public member functions, constructors, and destructors can be programmed
to also check class invariants. When class invariants are specified, they
are programmed in a public const
function named invariant
taking no argument and returning void.
Classes that do not have invariants, simply do not declare the invariant function.
This library uses template meta-programming (SFINAE-based introspection
techniques) to check invariants only for classes that declare a member
function named by BOOST_CONTRACT_INVARIANT_FUNC.
For example:
classu{public:// Must be public.voidinvariant()const{// Must be const.BOOST_CONTRACT_ASSERT(...);...}...};
This member function must be const
because contracts should not modify the object state (see Constant-Correctness).
This library will generate a compile-time error if the const
qualifier is missing (unless BOOST_CONTRACT_PERMISSIVE
is defined).
Any code can be programmed in the invariant
function, but it is recommended to keep this code simple using mainly assertions
and if-statements (to avoid programming complex invariants that might be
buggy and slow to check at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT to program
class invariant assertions because that enables this library to print informative
error messages when the asserted conditions are evaluated to be false (note
that this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` has commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call failure handlers boost::contract::entry_invariant_failure
or boost::contract::exit_invariant_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if the invariant
function throws an exception when invariants are checked at function entry
or exit respectively. By default, these handlers print an error message to
std::cerr and terminate the program calling
std::terminate (see Throw
on Failures to change these failure handlers to throw exceptions,
exit the program with an error code, etc.).
See Access Specifiers
to avoid making the invariant
member function public.
In this documentation the invariant
member function is often declared public
for simplicity. However, in production code it might not be acceptable
to augment the public members of a class adding the invariant
function (and that can be avoided using boost::contract::access
as explained in Access
Specifiers).
See BOOST_CONTRACT_INVARIANT_FUNC
to use a name different from invariant
(e.g., because invariant
clashes with other names in user-defined classes).
Contract assertions are not checked (not even class invariants) when data
members are accessed directly (this is different from Eiffel where even
accessing public data members checks class invariants). Therefore, it might
be best for both classes and
structs (and also unions, see Unions)
that have invariants to have no mutable public data members and to access
data members publicly only via appropriate public functions (e.g., setters
and getters) that can be programmed to check the class invariants using
this library.
See Volatile
Public Functions to program invariants for classes with volatile public functions.
Static
Class Invariants
Static public functions can be programmed to check static class invariants.
When static class invariants are specified, they are programmed in a public
static function named static_invariant taking no argument and
returning void. Classes that
do not have static class invariants, simply do not declare the static_invariant function.
This library uses template meta-programming (SFINAE-based introspection
techniques) to check static invariants only for classes that declare a
member function named by BOOST_CONTRACT_STATIC_INVARIANT_FUNC.
For example:
classu{public:// Must be public.staticvoidstatic_invariant(){// Must be static.BOOST_CONTRACT_ASSERT(...);...}...};
This member function must be static
(and it correctly cannot access the object this).
This library will generate a compile-time error if the static
classifier is missing (unless the BOOST_CONTRACT_PERMISSIVE
macro is defined).
Any code can be programmed in the static_invariant
function, but it is recommended to keep this code simple using mainly assertions
and if-statements (to avoid programming complex static invariants that might
be buggy and slow to check at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT to program
the assertions because that enables this library to print informative error
messages when the asserted conditions are evaluated to be false (note that
this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` has commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call failure handlers boost::contract::entry_invariant_failure
or boost::contract::exit_invariant_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if the static_invariant
function throws an exception when invariants are checked at function entry
or exit respectively. By default, these handlers print an error message to
std::cerr and terminate the program calling
std::terminate (see Throw
on Failures to change these failure handlers to throw exceptions,
exit the program with an error code, etc.).
See Access Specifiers
to avoid making static_invariant
member function public.
In this documentation the static_invariant
member function is often declared public
for simplicity. However, in production code it might not be acceptable
to augment the public members of a class adding the static_invariant
function (and that can be avoided using boost::contract::access
as explained in Access
Specifiers).
See BOOST_CONTRACT_STATIC_INVARIANT_FUNC
to use a name different from static_invariant
(e.g., because static_invariant
clashes with other names in user-defined classes). Rationale: In C++, it is not possible
to overload a member function based on the static
classifier. Therefore, this library has to use different names for the
member functions checking non-static and static class invariants (namely
for BOOST_CONTRACT_INVARIANT_FUNC
and for BOOST_CONTRACT_STATIC_INVARIANT_FUNC).
Constructors
Contracts for constructors are programmed using the boost::contract::constructor
function and the boost::contract::constructor_precondition
base class. For example (see public.cpp):
classunique_identifiers:privateboost::contract::constructor_precondition<unique_identifiers>{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(size()>=0);}public:// Contract for a constructor.unique_identifiers(intfrom,intto):boost::contract::constructor_precondition<unique_identifiers>([&]{BOOST_CONTRACT_ASSERT(from>=0);BOOST_CONTRACT_ASSERT(to>=from);}){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==(to-from+1));});// Constructor body.for(intid=from;id<=to;++id)vect_.push_back(id);}/* ... */};
It is not possible to specify preconditions using .precondition(...)
for constructors (this library will generate a compile-time error if .precondition(...) is used on the object returned by boost::contract::constructor).
Constructor preconditions are specified using the boost::contract::constructor_precondition
base class instead (same considerations as the ones made in Preconditions
apply also to the precondition functor passed to boost::contract::constructor_precondition).
Programmes should not access the object *this from constructor preconditions (because
the object does not exists yet before the constructor body is executed).
See No
Lambda Functions to enforce this constraint at compile-time (but
not recommended because of extra boiler-plate code).
Constructors without preconditions simply do not explicitly initialize
the boost::contract::constructor_precondition
base (because boost::contract::constructor_precondition
default constructor checks no contract). When the boost::contract::constructor_precondition
base class is used:
There is a MSVC bug that was fixed in MSVC 2013 for which lambdas cannot
be used in constructor member initialization lists for templates. On MSVC
compilers with that bug, an extra (static) member function can be used
(together with bind and
cref as needed) to program
constructor preconditions instead of using lambdas (see No
Lambda Functions).
It should be specified as the first class in the
inheritance list (so constructor preconditions are checked before initializing
any other base class or data member).
Its inheritance access specifier should always be private
(so this extra base class does not alter the public inheritance tree
of its derived classes).
It should never be declared as a virtual
base (because virtual bases are initialized only once across the entire
inheritance hierarchy preventing preconditions of other base classes
from being checked).
It takes the derived class as template parameter. Rationale: The boost::contract::constructor_precondition
takes the derived class as its template parameter (using the Curiously
Recursive Template Pattern, CRTP) so the instantiated template type
is unique for each derived class. This always avoids base class ambiguity
resolution errors even when multiple inheritance is used. Note that,
as already mentioned, virtual inheritance could not be used instead
of the template parameter here to resolve ambiguities (because virtual
bases are initialized only once by the outer-most derived class, and
that would not allow to properly check preconditions of all base classes).
A class can avoid inheriting from boost::contract::constructor_precondition
for efficiency but only when all its constructors have no preconditions.
It is possible to specify postconditions for constructors (see Postconditions),
but programmers should not access the old value of the object *this in constructor
postconditions (because the object did not exist yet before the constructor
body was executed).
See No
Lambda Functions to enforce this constraint at compile-time (but
not recommended because of extra boiler-plate code).
It is also possible to specify exceptions guarantees for constructors
(see Exception
Guarantees), but programmers should not access the object *this or its
old value in constructor exception guarantees (because the object did not
exist before executing the constructor body and it was not properly constructed
given the constructor body threw an exception).
See No
Lambda Functions to enforce these constraints at compile-time (but
not recommended because of extra boiler-plate code).
The boost::contract::constructor
function takes this as a parameter
(because constructors check class invariants, see Class
Invariants).
The boost::contract::constructor
function returns an RAII object that must always be assigned to a local variable
of type boost::contract::check
(otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL).
Furthermore, C++11 auto declarations
cannot be used here and the boost::contract::check
type must be explicitly specified (otherwise this library will generate a
compile-time error prior C++17 and a run-time error post C++17). The constructor
body is programmed right after the declaration of this RAII object.
At construction, the boost::contract::check
RAII object for constructors does the following (enclosing constructor entry):
Check static class invariants, by calling type-of(*this)::static_invariant() (but not non-static class invariants
because the object does not exist yet).
At destruction instead (enclosing constructor exit):
Check static class invariants, by calling type-of(*this)::static_invariant().
If the constructor body did not throw an exception:
Check non-static class invariants, by calling this->invariant().
Check postconditions, by calling the nullary functor s() passed to .postcondition(s).
Else:
Check exception guarantees, by calling the nullary functor e() passed to .except(e).
This together with C++ object construction mechanism of base classes and
the use of boost::contract::constructor_precondition
ensures that the constructor contracts are correctly checked at run-time
(see Constructor
Calls).
A constructor can avoid calling boost::contract::constructor
for efficiency but only when it has no postconditions, no exception guarantees,
and its class has no invariants (even if boost::contract::constructor
is not used by a derived class, contracts of base class constructors will
still be correctly checked by C++ object construction mechanism).
The default constructor and copy constructor automatically generated by
C++ will not check contracts. Therefore, unless these constructors are
not public or they have no preconditions, no postconditions, no exception
guarantees, and their class has no invariants, programmers should manually
define them using boost::contract::constructor
and boost::contract::constructor_precondition.
Similar considerations apply to all other constructors automatically generated
by C++ (e.g., the move constructor).
Private
and Protected Constructors
Private and protected constructors can omit boost::contract::constructor
(because they are not part of the public interface of the class so they are
not required to check class invariants, see Constructor
Calls). They could still use boost::contract::constructor_precondition
to check preconditions before member initializations, and even use boost::contract::function
(but not boost::contract::constructor)
to only check postconditions and exception guarantees without checking class
invariants and without calling .precondition(...)
(see Private
and Protected Functions). For example:
classu:privateboost::contract::constructor_precondition<u>{protected:// Contract for a protected constructor (same for private constructors).u():// Still use this base class to check constructor preconditions.boost::contract::constructor_precondition<u>([&]{BOOST_CONTRACT_ASSERT(...);...}){// Following will correctly not check class invariants.boost::contract::checkc=boost::contract::function()// Do not use `.precondition(...)` here..postcondition([&]{BOOST_CONTRACT_ASSERT(...);...}).except([&]{BOOST_CONTRACT_ASSERT(...);...});...// Constructor body.}...};Destructors
Contracts for destructors are programmed using boost::contract::destructor.
For example (see public.cpp):
classunique_identifiers:privateboost::contract::constructor_precondition<unique_identifiers>{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(size()>=0);}public:// Contract for a destructor.virtual~unique_identifiers(){// Following contract checks class invariants.boost::contract::checkc=boost::contract::destructor(this);// Destructor body here... (do nothing in this example).}/* ... */};
It is not possible to specify preconditions for destructors (this library
will generate a compile-time error if .precondition(...)
is used here and that is because destructors can be called at any time after
construction so they have no precondition). It is possible to specify postconditions
for destructors (see Postconditions,
and also Static
Public Functions for an example), but programmers should not access
the object *this
in destructor postconditions (because the object no longer exists after the
destructor body has been executed).
See No
Lambda Functions to enforce this constraint at compile-time (but
not recommended because of extra boiler-plate code).
It is also possible to specify exceptions guarantees for destructors
(see Exception
Guarantees, even if destructors should usually be programmed to not
throw exceptions in C++, in fact destructors are implicitly declared noexcept since C++11).
Exceptions guarantees in destructors can access both the object *this and
its old value because the object existed before executing the destructor
body and it still exists given the destructor body failed throwing an exception
so technically the object should still be properly constructed and satisfy
its class invariants.
The boost::contract::destructor
function takes this as a parameter
(because destructors check class invariants, see Class
Invariants).
The boost::contract::destructor
function returns an RAII object that must always be assigned to a local variable
of type boost::contract::check
(otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL).
Furthermore, C++11 auto declarations
cannot be used here and the boost::contract::check
type must be explicitly specified (otherwise this library will generate a
compile-time error prior C++17 and a run-time error post C++17). The destructor
body is programmed right after the declaration of this RAII object.
At construction, the boost::contract::check
RAII object for destructors does the following (enclosing destructor entry):
Check static and non-static class invariants, by calling type-of(*this)::static_invariant()ANDthis->invariant().
At destruction instead (enclosing destructor exit):
Check static class invariants, by calling type-of(*this)::static_invariant().
If the destructor body did not throw an exception:
Check postconditions, by calling the nullay functor s() passed to .postcondition(s).
Else (even if destructors should generally be programmed not to throw
in C++):
Check non-static class invariants, by calling this->invariant() (because the object was not successfully
destructed).
Check exception guarantees, by calling the nullary functor e() passed to .except(e).
This together with C++ object destruction mechanism of base classes ensures
that destructor contracts are correctly checked at run-time (see Destructor
Calls).
A destructor can avoid calling boost::contract::destructor
for efficiency but only when it has no postconditions, no exception guarantees,
and its class has no invariants (even if boost::contract::destructor
is not used by a derived class, contracts of base class destructors will
still be correctly checked by C++ object destruction mechanism).
The default destructor automatically generated by C++ will not check contracts.
Therefore, unless the destructor is not public or it has no postconditions,
no exception guarantees, and its class has no invariants, programmers should
manually define it using boost::contract::destructor.
Private
and Protected Destructors
Private and protected destructors can omit boost::contract::destructor
(because they are not part of the public interface of the class so they are
not required to check class invariants, see Destructor
Calls). They could use boost::contract::function
(but not boost::contract::destructor)
to only check postconditions and exception guarantees without checking class
invariants and without calling .precondition(...)
(see Private
and Protected Functions). For example:
classu{protected:// Contract for a protected destructor (same for private destructors).virtual~u(){// Following will correctly not check class invariants.boost::contract::checkc=boost::contract::function()// Do not use `.precondition(...)` here..postcondition([&]{BOOST_CONTRACT_ASSERT(...);...})// Could use `.except(...)` here in rare cases of destructors declared to throw.;...// Destructor body.}...};Public Functions
Contracts for public functions are programmed using boost::contract::public_function.
In this section, let's consider public functions that are not static, not
virtual, and do not override any function from base classes. For example
(see public.cpp):
classunique_identifiers:privateboost::contract::constructor_precondition<unique_identifiers>{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(size()>=0);}public:// Contract for a public function (but no static, virtual, or override).boolfind(intid)const{boolresult;boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(id>=0);}).postcondition([&]{if(size()==0)BOOST_CONTRACT_ASSERT(!result);});// Function body.returnresult=std::find(vect_.begin(),vect_.end(),id)!=vect_.end();}/* ... */};
It is possible to specify preconditions, postconditions, and exception guarantees
for public functions (see Preconditions,
Postconditions,
and Exception
Guarantees). When called from non-static public functions, the boost::contract::public_function
function takes this as a parameter
(because public functions check class invariants, see Class
Invariants).
The boost::contract::public_function
function returns an RAII object that must always be assigned to a local variable
of type boost::contract::check
(otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL).
Furthermore, C++11 auto declarations
cannot be used here and the boost::contract::check
type must be explicitly specified (otherwise this library will generate a
compile-time error prior C++17 and a run-time error post C++17). The public
function body is programmed right after the declaration of this RAII object.
At construction, the boost::contract::check
RAII object for public functions does the following (enclosing public function
entry):
Check static and non-static class invariants, by calling type-of(*this)::static_invariant()ANDthis->invariant().
Check preconditions, by calling the nullary functor r() passed to .precondition(r).
At destruction instead (enclosing public function exit):
Check static and non-static class invariants, by calling type-of(*this)::static_invariant()ANDthis->invariant()
(even if the function body threw an exception).
If the function body did not throw an exception:
Check postconditions, by calling the nullary functor s() passed to .postcondition(s).
Else:
Check exception guarantees, by calling the nullary functor e() passed to .except(e).
This ensures that public function contracts are correctly checked at run-time
(see Public
Function Calls).
A public function can avoid calling boost::contract::public_function
for efficiency but only when it has no preconditions, no postconditions,
no exception guarantees, it is not virtual, it does not override any virtual
function, and its class has no invariants.
The default copy assignment operator automatically generated by C++ will
not check contracts. Therefore, unless this operator is not public or it
has no preconditions, no postconditions, no exception guarantees, and its
class has no invariants, programmers should manually define it using boost::contract::public_function.
Similar considerations apply to all other operators automatically generated
by C++ (e.g., the move operator).
Virtual
Public Functions
Contracts for public functions are programmed using boost::contract::public_function.
In this section, let's consider public functions that are virtual but that
do not override any function from base classes. For example (see public.cpp):
classunique_identifiers:privateboost::contract::constructor_precondition<unique_identifiers>{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(size()>=0);}public:// Contract for a public virtual function (but no override).virtualintpush_back(intid,boost::contract::virtual_*v=0){// Extra `v`.intresult;boost::contract::old_ptr<bool>old_find=BOOST_CONTRACT_OLDOF(v,find(id));// Pass `v`.boost::contract::old_ptr<int>old_size=BOOST_CONTRACT_OLDOF(v,size());// Pass `v`.boost::contract::checkc=boost::contract::public_function(v,result,this)// Pass `v` and `result`..precondition([&]{BOOST_CONTRACT_ASSERT(id>=0);BOOST_CONTRACT_ASSERT(!find(id));// ID cannot be already present.}).postcondition([&](intconstresult){if(!*old_find){BOOST_CONTRACT_ASSERT(find(id));BOOST_CONTRACT_ASSERT(size()==*old_size+1);}BOOST_CONTRACT_ASSERT(result==id);});// Function body.vect_.push_back(id);returnresult=id;}/* ... */};
Virtual public functions must declare an extra trailing parameter of type
boost::contract::virtual_* with default value 0
(i.e., nullptr).
The name of this extra parameter is arbitrary, but v
is often used in this documentation.
This extra parameter is the last parameter and it has a default
value so it does not alter the calling interface of the virtual function
(callers will rarely, if ever, have to explicitly deal with this extra parameter
a part from when manipulating the virtual function type directly for function
pointer type-casting, etc.). Programmers must pass the extra virtual parameter
as the very first argument to all BOOST_CONTRACT_OLDOF
and boost::contract::public_function
calls in the virtual public function definition. Rationale: The boost::contract::virtual_* parameter is used by this library to determine
that a function is virtual (in C++ it is not possible to introspect if
a function is declared virtual).
Furthermore, this parameter is internally used by this library to implement
subcontracting (specifically to pass result and old values that are evaluated
by the overriding function to the contracts of overridden virtual functions
in base classes, and also to check preconditions, postconditions, and exception
guarantees of overridden virtual functions in OR
and AND
with contracts of the overriding virtual function).
When called from virtual public functions, the boost::contract::public_function
function takes this as a parameter
(because public functions check class invariants, see Class
Invariants). For virtual public functions returning void:
classu{public:// A void virtual public function (that does not override).virtualvoidf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){boost::contract::checkc=boost::contract::public_function(v,this)// No result parameter....precondition([&]{...}).postcondition([&]{...})// ...so nullary functor..except([&]{...});...}...}
For virtual public functions not returning void,
programmers must also pass a reference to the function return value as the
second argument to boost::contract::public_function.
In this case, the library will pass this return value reference to the postcondition
functor that must therefore take one single argument matching the return
type, otherwise this library will generate a compile-time error (the functor
parameter can be a constant reference const& to avoid extra copies of the return
value): Rationale: The extra function result parameter
taken by the functor passed to .postcondition(...)
is used by this library to pass the return value evaluated by the overriding
function to all its overridden virtual functions to support subcontracting.
classu{public:// A void virtual public function (that does not override).virtualtf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){tresult;boost::contract::checkc=boost::contract::public_function(v,result,this)// Result parameter....precondition([&]{...}).postcondition([&](tconst&result){...})// ...so unary functor..except([&]{...});...// Assign `result` at each return.}...}
It is the responsibility of the programmers to pass the extra virtual parameter
v to all BOOST_CONTRACT_OLDOF
and boost::contract::public_function
calls within virtual public functions, and also to pass the return value
reference after v to boost::contract::public_function
for non-void virtual public functions. This library cannot automatically
generate compile-time errors if programmers fail to do so (but in general
this will prevent the library from correctly checking contracts at run-time).
Rationale: This library does not require
programmers to specify the function type when using boost::contract::public_function
for non-overriding virtual public functions. Therefore, this library
does not know if the enclosing function has a non-void return type so
it cannot check if the return value reference is passed as required for
non-overriding virtual public functions. Instead the function type is
passed to this library for virtual public function overrides and that
also allows this library to give a compile-time error if the return value
reference is missing in those cases.
Mnemonics:
When v is present, always
pass it as the first argument to boost::contract::public_function
and BOOST_CONTRACT_OLDOF.
Always pass result to
boost::contract::public_function
right after v for non-void
functions.
For the rest, considerations made in Public
Functions apply to virtual public functions as well.
A virtual public function should always call boost::contract::public_function
(even if it has no preconditions, no postconditions, no exception guarantees,
and its class has no invariants), otherwise this library will not be able
to correctly use it for subcontracting.
Public
Function Overrides (Subcontracting)
Contracts for public functions are programmed using boost::contract::public_function.
In this section, let's consider public functions (virtual or not) that override
virtual public functions from one or more of their public base classes. For
example (see public.cpp):
In this documentation, function overrides are often marked with the code
comment /* override */. On
compilers that support C++11 virtual specifiers, the override
identifier can be used instead (override
is not used in the documentation simply because virtual specifiers are
not widely supported yet, even by compilers that support C++11 lambda functions).
classidentifiers#defineBASESpublicunique_identifiers:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Bases typedef.#undefBASESvoidinvariant()const{// Check in AND with bases.BOOST_CONTRACT_ASSERT(empty()==(size()==0));}public:// Contract for a public function override.intpush_back(intid,boost::contract::virtual_*v=0)/* override */{intresult;boost::contract::old_ptr<bool>old_find=BOOST_CONTRACT_OLDOF(v,find(id));boost::contract::old_ptr<int>old_size=BOOST_CONTRACT_OLDOF(v,size());boost::contract::checkc=boost::contract::public_function<override_push_back// Pass override type plus below function pointer...>(v,result,&identifiers::push_back,this,id)// ...and arguments..precondition([&]{// Check in OR with bases.BOOST_CONTRACT_ASSERT(id>=0);BOOST_CONTRACT_ASSERT(find(id));// ID can be already present.}).postcondition([&](intconstresult){// Check in AND with bases.if(*old_find)BOOST_CONTRACT_ASSERT(size()==*old_size);});// Function body.if(!find(id))unique_identifiers::push_back(id);// Else, do nothing.returnresult=id;}BOOST_CONTRACT_OVERRIDE(push_back)// Define `override_push_back`./* ... */};
The extra typedef declared using
BOOST_CONTRACT_BASE_TYPES
is required by this library for derived classes and it is internally used
to detect base classes for subcontracting (see Base
Classes). This library will generate a compile-time error if there
is no suitable virtual function to override in any of the public base classes
for subcontracting.
The compile-time error generated by the library in this case is similar
in principle to the error generated by the C++11 override
specifier, but it is limited to functions with the extra boost::contract::virtual_* parameter and searched recursively only
in public base classes passed
to BOOST_CONTRACT_BASE_TYPES
because only those are considered for subcontracting.
When called from public function overrides, the boost::contract::public_function
function template takes an explicit template argument override_function-name
that must be defined using BOOST_CONTRACT_OVERRIDE:
BOOST_CONTRACT_OVERRIDE(function-name)
This can be declared at any point in the public section of the enclosing
class (see Access
Specifiers to use BOOST_CONTRACT_OVERRIDE
also in a non-public section of the class). BOOST_CONTRACT_OVERRIDE
is used only once in a class for a given function name and overloaded functions
can reuse the same override_function-name
definition (see Function
Overloads). BOOST_CONTRACT_NAMED_OVERRIDE
can be used to generate a name different than override_function-name
(e.g., to avoid generating C++ reserved names containing double underscores
"__" for function
names that already start with an underscore "_",
see Named Overrides).
For convenience BOOST_CONTRACT_OVERRIDES
can be used with multiple function names instead of repeating BOOST_CONTRACT_OVERRIDE for each
function name (on compilers that support variadic macros). For example, for
three functions named f,
g, and h
(but same for any other number of functions), the following:
BOOST_CONTRACT_OVERRIDES(f,g,h)
Is equivalent to:
There is no equivalent of BOOST_CONTRACT_NAMED_OVERRIDE
that operates on multiple function names at once (BOOST_CONTRACT_NAMED_OVERRIDE
is not expected to be used often so it can simply be repeated multiple
times when needed).
BOOST_CONTRACT_OVERRIDE(f)BOOST_CONTRACT_OVERRIDE(g)BOOST_CONTRACT_OVERRIDE(h)
Public function overrides must always list the extra trailing parameter of
type boost::contract::virtual_* with default value 0
(i.e., nullptr), even when they
are not declared virtual, if
this parameter is present in the signature of the virtual function being
overridden from base classes. Programmers must pass the extra virtual parameter
as the very first argument to all BOOST_CONTRACT_OLDOF
and boost::contract::public_function
calls in the public function override definition (see Virtual
Public Functions).
When called from public function overrides, the boost::contract::public_function
function takes a pointer to the enclosing function, the object *this (because
public function overrides check class invariants, see Class
Invariants), and references to each function argument in the order
they appear in the function declaration. Rationale: The object this
is passed after the function pointer to follow std::bind's
syntax. The function pointer and references to all function arguments are
needed for public function overrides because this library has to internally
call overridden virtual public functions to check their contracts for subcontracting
(even if this library will not actually execute the bodies of the overridden
functions).
For public function overrides returning void:
classu{public:// A void public function override.voidf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_f>(v,&u::f,this,a_1,...,a_n)// No result parameter....precondition([&]{...}).postcondition([&]{...})// ...so nullary functor..except([&]{...});...}BOOST_CONTRACT_OVERRIDE(f)...}
For public function overrides not returning void,
programmers must also pass a reference to the function return value as the
second argument to boost::contract::public_function
(this library will generate a compile-time error otherwise). Rationale: As for non-overriding virtual
public functions, also public function overrides use the extra return value
parameter to pass it to the overridden functions when subcontracting. In
the case of public function overrides, this library has the function pointer
so it will generate a compile-time error if the function is non-void and
programmers forget to specify the extra return value parameter (this extra
error checking is not possible instead for non-overriding virtual public
functions because their contracts do not take the function pointer as a
parameter, see Virtual
Public Functions).
In this case, the library will pass this return value reference
to the postcondition functor that must therefore take one single argument
matching the return type, otherwise this library will generate a compile-time
error (the functor parameter can be a constant reference const& to avoid extra copies of the return
value, similarly to non-overriding non-void Virtual
Public Functions):
classu{public:// A non-void public function override.tf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0)/* override */{tresult;boost::contract::checkc=boost::contract::public_function<override_f>(v,result,&u::f,this,a_1,...,a_n)// Result parameter....precondition([&]{...}).postcondition([&](tconst&result){...})// ...so unary functor..except([&]{...});...// Assign `result` at each return.}BOOST_CONTRACT_OVERRIDE(f)...}
This library will throw boost::contract::bad_virtual_result_cast
if programmers specify return values for public function overrides in derived
classes that are not consistent with the return types of the virtual public
functions being overridden in the base classes. Rationale: The boost::bad_any_cast
exception was not used here because it does not print the from- and to-
type names (so it is not descriptive enough).
It is the responsibility of the programmers to pass the extra virtual parameter
v to all BOOST_CONTRACT_OLDOF
and boost::contract::public_function
calls within public function overrides, and also to pass the return value
reference after v to boost::contract::public_function
for non-void public function overrides. This library cannot always generate
compile-time errors if programmers fail to do so (but in general this will
prevent the library from correctly checking contracts at run-time).
Mnemonics:
When override_...
is present, always pass it as template parameter to boost::contract::public_function.
When v is present, always
pass it as the first argument to boost::contract::public_function
and BOOST_CONTRACT_OLDOF.
Always pass result to
boost::contract::public_function
right after v for non-void
functions.
At construction, the boost::contract::check
RAII object for public function overrides does the following (enclosing public
function override entry):
Check static and non-static class invariants for all overridden bases
and for the derived class in AND
with each other, by calling type-of(overridden-base_1)::static_invariant()ANDoverridden-base_1.invariant()AND...
type-of(overridden-base_n)::static_invariant()ANDoverridden-base_n.invariant()ANDtype-of(*this)::static_invariant()ANDthis->invariant().
Check preconditions for all overridden base functions and for the overriding
derived function in OR
with each other, by calling the nullary functors r_1()OR...
r_n()ORr()
passed to .precondition(r_1), ... .precondition(r_n), .precondition(r) for all of the overridden and overriding
functions respectively.
At destruction instead (enclosing public function override exit):
Check static and non-static class invariants for all overridden bases
and for the derived class in AND
with each other, by calling type-of(overridden-base_1)::static_invariant()ANDoverridden-base_1.invariant()AND...
type-of(overridden-base_n)::static_invariant()ANDoverridden-base_n.invariant()ANDtype-of(*this)::static_invariant()ANDthis->invariant()
(even if the function body threw an exception).
If the function body did not throw an exception:
Check postconditions for all overridden base functions and for
the overriding derived function in AND
with each other, by calling the nullary functors s_1()AND...
s_n()ANDs()
passed to .postcondition(s_1), ... .postcondition(s_n), .postcondition(s) for all of the overridden and
overriding functions respectively (or the unary functors s_1(result)AND...
s_n(result)ANDs(result) for non-void public function overrides).
Else:
Check exception guarantees for all overridden base functions and
for the overriding derived function in AND
with each other, by calling the nullary functors e_1()AND...
e_n()ANDe()
passed to .except(e_1), ... .except(e_n), .except(e) for all of the overridden and
overriding functions respectively.
This ensures that contracts and subcontracts of public function overrides
are correctly checked at run-time in accordance with the substitution
principle (see Public
Function Calls).
For the rest, considerations made in Virtual
Public Functions apply to public function overrides as well.
A public function override should always call boost::contract::public_function
(even if it has no preconditions, no postconditions, no exception guarantees,
and its class has no invariants), otherwise this library will not be able
to correctly use it for subcontracting.
Base
Classes (Subcontracting)
In order for this library to support subcontracting, programmers must specify
the bases of a derived class declaring a public member type named base_types via a typedef
using BOOST_CONTRACT_BASE_TYPES.
For example (see base_types.cpp):
classchars#defineBASES/* local macro (for convenience) */\privateboost::contract::constructor_precondition<chars>,\publicunique_chars,\publicvirtualpushable<char>,\virtualprotectedhas_size,\privatehas_empty:BASES// Bases of this class.{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Bases typedef.#undefBASES// Undefine local macro./* ... */
For convenience, a local macro named BASES
can be used to avoid repeating the base list twice (first in the derived
class declaration classclass-name:base-list
and then again when invoking BOOST_CONTRACT_BASE_TYPES(base-list)). Being a local macro, BASES
must be undefined using #undefBASES after it is used to declare
the base_typestypedef (to avoid name clashes and macro redefinition
errors).
The name of this local macro is arbitrary, but BASES
is often used in this documentation.
BOOST_CONTRACT_BASE_TYPES
is a variadic macro and accepts a list of bases separated by commas (see
No
Macros to program base_types
without using macros). As already noted in Constructors,
when the extra base boost::contract::constructor_precondition
is used to program constructor preconditions, its inheritance access level
must always be private and it
must be specified as the very first base.
Each base passed to BOOST_CONTRACT_BASE_TYPES
must explicitly specify its inheritance access level
public, protected,
or private (but virtual is optional and can be specified
either before or after the access level as usual in C++). This library
will generate a compile-time error if the first base is missing its inheritance
access level, but this library will not be able to always generate an error
if the access level is missing for bases after the first one. Rationale: This library explicitly requires
the inheritance access level because derived classes must subcontract
only from public bases, but not from protected or private bases (see
Public
Function Calls). BOOST_CONTRACT_BASE_TYPES
inspects each inheritance access level using preprocessor meta-programming
and removes non-public bases from the list of bases internally used for
subcontracting. However, this library cannot always detect when programmers
forget to specify the inheritance access level because, when commas are
used to separate template parameters passed to base classes, the preprocessor
will not be able to correctly use commas to identify the next base class
token in the inheritance list (the preprocessor cannot distinguish between
commas that are not protected by round parenthesis, like the ones used
in templates). Therefore, this library uses the inheritance access level
keyword public, protected, or private
instead of commas , for
the preprocessor to correctly find the next base class token in the inheritance
list (thus inheritance access levels must always be explicit specified
by programmers for each base).
It is the responsibility of the programmers to make sure that
all bases passed to BOOST_CONTRACT_BASE_TYPES
explicitly specify their inheritance access level (inheritance access levels
are instead optional in C++ because private
is implicitly assumed for class
types and public for struct types).
Mnemonics:
Always explicitly specify the inheritance access level public, protected,
or private for base classes
passed to BOOST_CONTRACT_BASE_TYPES.
See Access Specifiers
to avoid making the base_types
member type public.
In this documentation the base_type
member type is often declared public
for simplicity. However, in production code it might not be acceptable
to augment the public members of a class adding the base_types
type (and that can be avoided using boost::contract::access
as explained in Access
Specifiers).
See BOOST_CONTRACT_BASES_TYPEDEF
to use a name different from base_types
(e.g., because base_types
clashes with other names in user-defined classes).
Static
Public Functions
Contracts for public functions are programmed using boost::contract::public_function.
In this section, let's consider static public functions. For example (see
static_public.cpp):
template<classC>classmake{public:staticvoidstatic_invariant(){// Static class invariants.BOOST_CONTRACT_ASSERT(instances()>=0);}// Contract for a static public function.staticintinstances(){// Explicit template parameter `make` (check static invariants).boost::contract::checkc=boost::contract::public_function<make>();returninstances_;// Function body.}/* ... */
It is possible to specify preconditions, postconditions, and exception guarantees
for static public functions (see Preconditions,
Postconditions,
and Exception
Guarantees). When called from static public functions, boost::contract::public_function
cannot take the object this
as a parameter (because there is no object this
in static member functions) so the enclosing class type is specified via
an explicit template parameter as in boost::contract::public_function<class-type>
(the class type is required to check static class invariants, see Class
Invariants):
classu{public:// A static public function.staticvoidf(){boost::contract::checkc=boost::contract::public_function<u>()// Class type `u` as explicit template parameter..precondition([&]{...}).postcondition([&]{...}).except([&]{...});...}...};
The boost::contract::public_function
function returns an RAII object that must be assigned to a local variable
of type boost::contract::check
(otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL).
Furthermore, C++11 auto declarations
cannot be used here and the boost::contract::check
type must be explicitly specified (otherwise this library will generate a
compile-time error prior C++17 and a run-time error post C++17). The static
public functions body is programmed right after the declaration of this RAII
object.
At construction, the boost::contract::check
RAII object for static public functions does the following (enclosing static
public function entry):
Check static class invariants, by calling class-type::static_invariant() (but never non-static class invariants).
Check preconditions, by calling the nullary functor r() passed to .precondition(r).
At destruction instead (enclosing static public function exit):
Check static class invariants, by calling class-type::static_invariant() (even if the function body threw an
exception, but never non-static class invariants).
If the function body did not throw an exception:
Check postconditions, by calling the nullary functor s() passed to .postcondition(s).
Else:
Check exception guarantees, by calling the nullary functor e() passed to .except(e).
This ensures that static public function contracts are correctly checked
at run-time (static public functions do not subcontract because they have
no object this and therefore
there is no inheritance, see Public
Function Calls).
A static public function can avoid calling boost::contract::public_function
for efficiency but only when it has no preconditions, no postconditions,
no exception guarantees, and its class has no static invariants (the class
can still have non-static invariants or base classes instead).
Advanced
This section is a guide to advanced usage of this library.
Pure
Virtual Public Functions
In C++, pure virtual functions are allowed to have a default
implementation as long as such implementation is programmed out-of-line
so defined outside the class declaring the pure virtual function virtual...=0;.
Contracts for pure virtual public functions are programmed using the boost::contract::public_function
function like for (non-pure) virtual public functions (all consideration
made in Virtual
Public Functions apply). However, contracts have to be programmed
out-of-line, in the default implementation of the pure virtual function.
For example (see pure_virtual_public.cpp):
template<typenameIterator>classrange{public:// Pure virtual function declaration (contract in definition below).virtualIteratorbegin(boost::contract::virtual_*v=0)=0;/* ... */};// Pure virtual function default implementation (out-of-line in C++).template<typenameIterator>Iteratorrange<Iterator>::begin(boost::contract::virtual_*v){Iteratorresult;// As usual, virtual pass `result` right after `v`...boost::contract::checkc=boost::contract::public_function(v,result,this).postcondition([&](Iteratorconst&result){if(empty())BOOST_CONTRACT_ASSERT(result==end());});// Pure function body (never executed by this library).assert(false);returnresult;}
This library will never actually execute the pure virtual function body while
it is calling the pure virtual function default implementation to check contracts
for subcontracting. Therefore, programmers can safely assert(false)
at the beginning of the body if they intend for that body to never be executed
(or they can program a working body in case they need to use pure virtual
function default implementations as usual in C++).
Subcontracting
Preconditions Always True or False
As seen in Public
Function Overrides, preconditions of overriding public functions are
checked in OR
with preconditions of overridden virtual public functions. Therefore, if
a virtual public function in a base class specifies no precondition then
preconditions specified by all its overriding functions in derived classes
will have no effect (because when checked in OR
with the overridden function from the base class that has no preconditions,
they will always pass):
classu{// Some base class.public:virtualvoidf(boost::contract::virtual_*v=0){boost::contract::checkc=boost::contract::public_function(v,this)// No preconditions, same as `ASSERT(true)`....;...}...};
This correctly reflects the fact that the overridden function in the base
class can be called from any context (because it has no precondition) and
so must all its overriding functions in all derived classes in accordance
to the substitution
principle.
This consequence of the substitution
principlethat if any function in an inheritance hierarchy
has no preconditions, then preconditions on functions overriding it have
no useful effect is also explicitly mentioned in the contract documentation
of the D Programming Language (see [Bright04]).
In other words, the code above has the same effect as declaring
the virtual public function in the base class with a single precondition
BOOST_CONTRACT_ASSERT(true) that
will always trivially pass:
classu{// Some base class.public:virtualvoidf(boost::contract::virtual_*v=0){boost::contract::checkc=boost::contract::public_function(v,this).precondition([]{BOOST_CONTRACT_ASSERT(true);// Same as no preconditions.})...;...}...};
On the flip side, programmers might sometimes consider to declare a pure
virtual public function in a base class with a single precondition BOOST_CONTRACT_ASSERT(false) that
will always fail. This indicates that the pure virtual public function can
never be called unless it is redefined by a derived class (which is already
the case with C++ pure virtual functions) and also that the base class designers
have intentionally left it up to derived classes to specify preconditions
for the pure virtual function in question. This technique might make sense
only for preconditions of pure virtual public functions (otherwise BOOST_CONTRACT_ASSERT(false) will
prevent calling virtual public functions in concrete bases). For example
(see named_override.cpp):
template<typenameT>classgeneric_unary_pack{public:virtualvoid_1(Tconst&value,boost::contract::virtual_*v=0)=0;virtualT_1(boost::contract::virtual_*v=0)const=0;};template<typenameT>voidgeneric_unary_pack<T>::_1(Tconst&value,boost::contract::virtual_*v){boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(false);// Defer preconditions to overrides.});assert(false);}/* ... */
That said, the need to declare such a precondition BOOST_CONTRACT_ASSERT(false)
that will always fail might also be an indication that the base class interface
is not correctly designed. In general, the base class interface should still
contain all functions (eventually as pure virtual) that are necessary to
program its contracts.
Optional
Return Values
It is possible to use boost::optional
to handle return values when programmers cannot construct the result variable
at its point of declaration before the contract (e.g., because an appropriate
constructor for the return type is not available at that point, or just because
it would be too expensive to execute an extra initialization of the return
value at run-time). Rationale: This library uses boost::optional instead of std::optional
to support a larger number of compilers and their versions (because std::optional was not available before C++17).
For example (see optional_result.cpp):
template<unsignedIndex,typenameT>T&get(std::vector<T>&vect){boost::optional<T&>result;// Result not initialized here...boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(Index<vect.size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(*result==vect[Index]);});// Function body (executed after preconditions checked).return*(result=vect[Index]);// ...result initialized here instead.}
In this example the return type is a reference so it does not have default
constructor that can be used to initialize result
when it is declared before the contract declaration. In addition, Index needs to be validated to be smaller
than size()
by the precondition before it can be used to retrieve the reference to assign
to result so vect[Index] cannot be used to initialize result when it is declared before the contract
declaration. Therefore, boost::optional
is used to defer result real
initialization until the execution of the function body, after the contract
declaration, where Index
has been validated by the precondition and vect[Index] can be safely evaluated to initialize result.
As seen in Return Values,
it is the responsibility of the programmers to ensure that result is always set to the return value
(when the function exits without trowing an exception). This also ensures
that result is always set
before the postconditions are checked so programmers can always dereference
result in postconditions
to access the return value (using operator* and operator-> as usual with boost::optional,
and without having to explicitly check if result
is an empty boost::optional object or not). This can be done
ensuring that allreturn
statements in the function are of the form:
boost::optional<return-type>result;...return*(result=return-expression);// Assign `result` at each return.Optional
Results in Virtual Public Functions
Similarly, boost::optional can be used to handle the return
value passed to contracts of virtual public functions (pure or not) and of
public function overrides. As seen in Pure
Virtual Public Functions, Virtual
Public Functions, and Public
Function Overrides, in these cases the return value result must be passed as a parameter to
boost::contract::public_function
right after the parameter v
of type boost::contract::virtual_*. Then the functor passed to .postcondition(...) takes one single parameter of type
boost::optional<return-typeconst&>const&.
For example (see optional_result_virtual.cpp):
template<typenameT>T&accessible<T>::at(unsignedindex,boost::contract::virtual_*v){boost::optional<T&>result;// Pass `result` right after `v`...boost::contract::checkc=boost::contract::public_function(v,result,this).precondition([&]{BOOST_CONTRACT_ASSERT(index<size());})// ...plus postconditions take `result` as a parameter (not capture)..postcondition([&](boost::optional<Tconst&>const&result){BOOST_CONTRACT_ASSERT(*result==operator[](index));});assert(false);return*result;}
The inner const&
in the postcondition functor parameter type boost::optional<...const&>...
is mandatory (while the outer const& in the postcondition functor parameter
type boost::optional<...>const&
is not). Rationale: This library requires the postcondition
functor parameter to be of type boost::optional<...const&> so the return value does not have
to be copied (because of &)
while postconditions are still not allowed to change its value (because
of const, see Constant-Correctness).
In addition, programmers are encouraged to declare the postcondition functor
to take its argument also as a constant reference boost::optional<...const&>const& to avoid possibly expensive copies
of the boost::optional type itself.
Private
and Protected Functions
Private and protected functions do not check class invariants (because they
are not part of the public class interface) and they do not subcontract (because
they are not accessible at the calling site where the substitution
principle applies, see Function
Calls). However, programmers may still want to specify preconditions
and postconditions for private and protected functions when they want to
check correctness of their implementation and use (from within the class,
base classes, friend classes or functions, etc.). When programmers decide
to specify contracts for private and protected functions, they can use boost::contract::function
(because, like for non-member functions, this does not check class invariants
and does not subcontract). For example (see private_protected.cpp):
classcounter{protected:// Protected functions use `function()` (like non-members).voidset(intn){boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(n<=0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==n);});n_=n;}private:// Private functions use `function()` (like non-members).voiddec(){boost::contract::old_ptr<int>old_get=BOOST_CONTRACT_OLDOF(get());boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(get()+1>=std::numeric_limits<int>::min());}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==*old_get-1);});set(get()-1);}intn_;/* ... */
Considerations made in Non-Member
Functions apply to private and protected functions as well. See Constructors and Destructors on how to
program contracts for private and protected constructors and destructors
instead.
Virtual
Private and Protected Functions
When private and protected functions are virtual they should still declare
the extra virtual parameter of type boost::contract::virtual_* with default value 0
(see Virtual
Public Functions) even if that parameter does not have to be passed
to BOOST_CONTRACT_OLDOF
and boost::contract::function
takes no such an argument (so the extra virtual parameter will remain unused
and it does not need a name).
Technically, the extra virtual parameter can still be passed to BOOST_CONTRACT_OLDOF but that is
not necessary and it has no effect so it is not done in this documentation.
That is necessary otherwise the private and protected virtual
functions cannot be overridden by public functions in derived classes that
specify contracts (because the boost::contract::virtual_*=0
parameter has to be part of signatures for public function overrides). For
example (see private_protected_virtual.cpp):
classcounter{// Virtual private and protected functions still declare extra// `virtual_* = 0` parameter (otherwise they cannot be overridden), but...protected:virtualvoidset(intn,boost::contract::virtual_*=0){boost::contract::checkc=boost::contract::function()// ...no `v`..precondition([&]{BOOST_CONTRACT_ASSERT(n<=0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==n);});n_=n;}private:virtualvoiddec(boost::contract::virtual_*=0){boost::contract::old_ptr<int>old_get=BOOST_CONTRACT_OLDOF(get());// ...no `v`.boost::contract::checkc=boost::contract::function()// ...no `v`..precondition([&]{BOOST_CONTRACT_ASSERT(get()+1>=std::numeric_limits<int>::min());}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==*old_get-1);});set(get()-1);}intn_;/* ... */
However, public functions in derived classes overriding private or protected
virtual functions from base classes shall not specify the extra override_...
template parameter to boost::contract::public_function
because the overridden functions are private or protected and, not being
public, they do not participate to subcontracting (this library will generate
a compile-time error if override_... is specified because there will be no
virtual public function to override from the base class).
For example (see private_protected_virtual.cpp):
classcounter10#defineBASESpubliccounter:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASES// Overriding from non-public members so no subcontracting, no override_...virtualvoidset(intn,boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(n%10==0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==n);});counter::set(n);}virtualvoiddec(boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<int>old_get=BOOST_CONTRACT_OLDOF(v,get());boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(get()+10>=std::numeric_limits<int>::min());}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==*old_get-10);});set(get()-10);}/* ... */
Furthermore, using multiple inheritance it is possible to override functions
that are private or protected from one base but public from another base.
In this case, public function overrides in derived classes will specify the
extra override_...
template parameter to boost::contract::public_function
(because the overridden functions are private or protected in one base and
those do not participate to subcontracting, but public in another base and
these participate to subcontracting instead). For example (see private_protected_virtual_multi.cpp):
classcountable{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(get()<=0);}virtualvoiddec(boost::contract::virtual_*v=0)=0;virtualvoidset(intn,boost::contract::virtual_*v=0)=0;virtualintget(boost::contract::virtual_*v=0)const=0;};/* ... */classcounter10#defineBASESpubliccountable,publiccounter// Multiple inheritance.:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASES// Overriding from public members from `countable` so use `override_...`.virtualvoidset(intn,boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_set>(v,&counter10::set,this,n).precondition([&]{BOOST_CONTRACT_ASSERT(n%10==0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==n);});counter::set(n);}virtualvoiddec(boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<int>old_get=BOOST_CONTRACT_OLDOF(v,get());boost::contract::checkc=boost::contract::public_function<override_dec>(v,&counter10::dec,this).precondition([&]{BOOST_CONTRACT_ASSERT(get()+10>=std::numeric_limits<int>::min());}).postcondition([&]{BOOST_CONTRACT_ASSERT(get()==*old_get-10);});set(get()-10);}BOOST_CONTRACT_OVERRIDES(set,dec)/* ... */
Unfortunately, the code above does not compile on MSVC (at least up to
Visual Studio 2015) because MSVC incorrectly gives a compile-time error
when SFINAE fails due to private or protected access levels. Instead, GCC
and Clang correctly implement SFINAE failures due to private and protected
functions so the code above correctly complies on GCC and Clang. Therefore,
currently it is not possible to override a function that is public in one
base but private or protected in other base using this library on MSVC
(at least up to Visual Studio 2015), but that can correctly be done on
GCC or Clang instead.
Friend Functions
In general, friend functions are not member functions so boost::contract::function
is used to program their contracts and all considerations made in Non-Member
Functions apply. For example (see friend.cpp):
classbuffer;classbyte{friendbooloperator==(bufferconst&left,byteconst&right);private:charvalue_;/* ... */classbuffer{// Friend functions are not member functions...friendbooloperator==(bufferconst&left,byteconst&right){// ...so check contracts via `function` (which won't check invariants).boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(!left.empty());BOOST_CONTRACT_ASSERT(!right.empty());});for(charconst*x=left.values_.c_str();*x!='\0';++x){if(*x!=right.value_)returnfalse;}returntrue;}private:std::stringvalues_;/* ... */
However, in some cases a friend function might take an object as parameter
and it can be logically considered an extension of that object's public interface
(essentially at the same level as the object's public functions). In these
cases, programmers might chose to program the friend function contracts using
boost::contract::public_function
(instead of boost::contract::function)
so to also check the class invariants of the object passed as parameter (and
not just pre- and postconditions). For example (see friend_invariant.cpp):
Rationale: Contract programming proposals
for C++ like [N1962] do not provide
a mechanism for friend functions to check class invariants of objects passed
as parameters. In other words, these proposals do not enable contracts
to recognize that in C++ some friend functions logically act as if they
were part of the public interface of the objects they take as parameters.
This is reasonable for proposals that add contracts to the core language
because friend functions are not always meant to extend an object public
interface and C++ does not provide a mechanism to programmatically specify
when they do and when they do not. However, this library provides the flexibility
to let programmers manually specify when friend functions should also check
class invariants of the objects they take as parameters (using boost::contract::public_function)
and when they should not (using boost::contract::function
instead).
template<typenameT>classpositive{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(value()>0);}// Can be considered an extension of enclosing class' public interface...friendvoidswap(positive&object,T&value){boost::contract::old_ptr<T>old_object_value=BOOST_CONTRACT_OLDOF(object.value());boost::contract::old_ptr<T>old_value=BOOST_CONTRACT_OLDOF(value);// ...so it can be made to check invariants via `public_function`.boost::contract::checkc=boost::contract::public_function(&object).precondition([&]{BOOST_CONTRACT_ASSERT(value>0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(object.value()==*old_value);BOOST_CONTRACT_ASSERT(value==*old_object_value);});Tsaved=object.value_;object.value_=value;value=saved;}private:Tvalue_;/* ... */
This technique can also be extended to friend functions that take multiple
objects as parameters and can be logically considered extensions to the public
interfaces of each of these objects. For example:
// Can be considered an extension of multiple objects' public interfaces.friendvoidf(class1&object1,class2*object2,type3&value3){// Check preconditions.boost::contract::checkpre=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(object2!=nullptr);...});// Check class invariants for each object (programmers chose the order).boost::contract::checkinv1=boost::contract::public_function(&object1);boost::contract::checkinv2=boost::contract::public_function(object2);// Check postconditions and exception guarantees.boost::contract::checkpostex=boost::contract::function().postcondition(...).except(...);...// Function body.}
Changing the order of the boost::contract::check
declarations above, programmers can chose the order for checking class invariants
among the different objects passed to the friend function and also whether
to check these invariants before or after preconditions, postconditions,
and exception guarantees of the friend function (see Non-Member
Functions and Public
Functions for information on how the RAII objects returned by boost::contract::function
and boost::contract::public_function
check contract conditions). The example above is programmed to check class1 invariants before class2 invariants (but that order could
have been inverted if programmers so chose).
In the example above, preconditions are intentionally programmed to be
checked before class invariants so the objects passed to the friend function
can be validated by the preconditions before they are passed as pointers
to boost::contract::public_function
(e.g., check object2 is
not null). (Within member functions instead, the object pointer this is always well-formed, its validation
is never needed, and boost::contract::public_function
checks class invariants before checking preconditions so programming preconditions
can be simplified assuming the class invariants are satisfied already,
see Public
Function Calls.)
Function
Overloads
No special attention is required when using this library with overloaded
functions or constructors. The only exception is for the function pointer
passed to boost::contract::public_function
from public function overrides (see Public
Function Overrides). When the name of public function override are
also overloaded, the related function pointer cannot be automatically deduced
by the compiler so programmers have to use static_cast
to resolve ambiguities (as usual with pointers to overloaded functions in
C++). Rationale: In order to avoid copies, this
library takes all function arguments and the return value passed to boost::contract::public_function
as references when used within public function overrides. Therefore, the
library cannot differentiate when the actual function argument and return
types are passed by reference and when they are not. As a result, the library
cannot automatically reconstruct the type of the enclosing public function
so this type must be deduced from the function pointer passed by programmers
to boost::contract::public_function.
When this automatic deduction is not possible due to overloaded function
names, programmers must explicitly use static_cast
to resolve ambiguities as usual in C++ with pointers to overloaded functions.
For example, note how static_cast
is used in the following calls to boost::contract::public_function
(see overload.cpp):
classstring_lines#defineBASESpubliclines:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_OVERRIDES(str)// Invoked only once for all `str` overloads.std::stringstr(boost::contract::virtual_*v=0)const/* override */{std::stringresult;boost::contract::checkc=boost::contract::public_function<override_str>(v,result,// `static_cast` resolves overloaded function pointer ambiguities.static_cast<std::string(string_lines::*)(boost::contract::virtual_*)const>(&string_lines::str),this);returnresult=str_;}// Overload on (absence of) `const` qualifier.std::string&str(boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_str>(v,str_,// `static_cast` resolves overloaded function pointer ambiguities.static_cast<std::string&(string_lines::*)(boost::contract::virtual_*)>(&string_lines::str),this);returnstr_;}BOOST_CONTRACT_OVERRIDES(put)// Invoked only once for all `put` overloads.voidput(std::stringconst&x,boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<std::string>old_str=BOOST_CONTRACT_OLDOF(v,str());boost::contract::checkc=boost::contract::public_function<override_put>(v,// `static_cast` resolves overloaded function pointer ambiguities.static_cast<void(string_lines::*)(std::stringconst&,boost::contract::virtual_*)>(&string_lines::put),this,x).postcondition([&]{BOOST_CONTRACT_ASSERT(str()==*old_str+x+'\n');});str_=str_+x+'\n';}// Overload on argument type.voidput(charx,boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<std::string>old_str=BOOST_CONTRACT_OLDOF(v,str());boost::contract::checkc=boost::contract::public_function<override_put>(v,// `static_cast` resolves overloaded function pointer ambiguities.static_cast<void(string_lines::*)(char,boost::contract::virtual_*)>(&string_lines::put),this,x).postcondition([&]{BOOST_CONTRACT_ASSERT(str()==*old_str+x+'\n');});str_=str_+x+'\n';}// Overload on argument type and arity (also with default parameter).voidput(intx,booltab=false,boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<std::string>old_str=BOOST_CONTRACT_OLDOF(v,str());boost::contract::checkc=boost::contract::public_function<override_put>(v,// `static_cast` resolves overloaded function pointer ambiguities.static_cast<void(string_lines::*)(int,bool,boost::contract::virtual_*)>(&string_lines::put),this,x,tab).postcondition([&]{std::ostringstreams;s<<x;BOOST_CONTRACT_ASSERT(str()==*old_str+(tab?"\t":"")+s.str()+'\n');});std::ostringstreams;s<<str_<<(tab?"\t":"")<<x<<'\n';str_=s.str();}private:std::stringstr_;};
Overloaded functions have the same function name so the same override_function-name
type can be reused as template parameter for all boost::contract::public_function
calls in a given class. Therefore, BOOST_CONTRACT_OVERRIDE
only needs to be invoked once for a function name in a given class, even
when that function name is overloaded.
Lambdas,
Loops, Code Blocks (and constexpr)
While contracts are usually most useful to program specifications of functions
and class interfaces, this library also allows to check contract conditions
for implementation code (lambda functions, loops, code blocks, etc.).
Lambda functions are not member functions, they are not part of class public
interfaces so they do not check class invariants and they do not subcontract.
They can use boost::contract::function
to specify preconditions, postconditions, and exception guarantees (considerations
made in Non-Member
Functions apply). For example (see lambda.cpp):
inttotal=0;std::for_each(v.cbegin(),v.cend(),// Contract for a lambda function.[&total](intconstx){boost::contract::old_ptr<int>old_total=BOOST_CONTRACT_OLDOF(total);boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(total<std::numeric_limits<int>::max()-x);}).postcondition([&]{BOOST_CONTRACT_ASSERT(total==*old_total+x);});total+=x;// Lambda function body.});
Similarly, boost::contract::function
can be used to program preconditions, postconditions, and exception guarantees
for loops. For example, for a for-loop but same for while- and all other
loops (see loop.cpp):
inttotal=0;// Contract for a for-loop (same for while- and all other loops).for(std::vector<int>::const_iteratori=v.begin();i!=v.end();++i){boost::contract::old_ptr<int>old_total=BOOST_CONTRACT_OLDOF(total);boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(total<std::numeric_limits<int>::max()-*i);}).postcondition([&]{BOOST_CONTRACT_ASSERT(total==*old_total+*i);});total+=*i;// For-loop body.}
More in general, boost::contract::function
can be used to program preconditions, postconditions, and exception guarantees
of any block of code in a given function. For example (see code_block.cpp):
/* ... */// Contract for a code block.{// Code block entry (check preconditions).boost::contract::old_ptr<int>old_total=BOOST_CONTRACT_OLDOF(total);boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(v.size()==3);}).postcondition([&]{BOOST_CONTRACT_ASSERT(total==*old_total+v[0]+v[1]+v[2]);});total+=v[0]+v[1]+v[2];// Code block body.}// Code block exit (check postconditions and exceptions guarantees)./* ... */
The library does not support contracts for functions and classes declared
constexpr. Rationale: In general, it might be useful
to specify contracts for constexpr
functions and literal classes. However, the current implementation of this
library cannot support contracts for constexpr
functions and classes because C++ does not currently allow constexpr functions to do the following:
Declare local variables of (literal) types with non-trivial constexpr destructors (this RAII technique
is used by this library to check invariants, postconditions, and exceptions
guarantees at exit); Call other constexpr
functions using try-catch statements (used by this library to report contract
assertion failures and catch any other exception that might be thrown when
evaluating the asserted conditions); Use lambda functions (used by this
library for convenience to program functors that that check preconditions,
postconditions, and exception guarantees). Also note that even if supported,
contracts for constexpr functions
probably would not use old values (because constexpr
prevents functions from having any side effect visible to the caller and
variables recording such side-effects are usually the candidates for old
value copies) and subcontracting (because constexpr
functions cannot be virtual).
Implementation
Checks
This library provides also a mechanism to check assertions within implementation
code (differently from preconditions, postconditions, exceptions guarantees,
and class invariants that are instead checked before or after code that implements
a function body). These implementation checks are programmed
using a nullary functor that is directly assigned to a boost::contract::check
object declaration right at the place within the code where the checks need
to be performed (without calling boost::contract::function,
boost::contract::public_function,
etc. in this case). For example (see check.cpp):
intmain(){// Implementation checks (via nullary functor).boost::contract::checkc=[]{BOOST_CONTRACT_ASSERT(gcd(12,28)==4);BOOST_CONTRACT_ASSERT(gcd(4,14)==2);};return0;}
The implementation check functor should capture all the variables that it
needs for its assertions. These variables can be captured by value when the
overhead of copying such variables is acceptable. In any case, programmers
should not write implementation checks that modify the value of the captured
variables, even when those are captured by reference (see Constant-Correctness).
Any code can be programmed in the implementation check functor, but it is
recommended to keep this code simple using mainly assertions and if-statements
(to avoid programming complex checks that might be buggy and also slow to
check at run-time). It is also recommended to use BOOST_CONTRACT_ASSERT
to program the assertions because that enables this library to print informative
error messages when the asserted conditions are evaluated to be false (note
that this is not a variadic macro, see No
Macros):
BOOST_CONTRACT_ASSERT(boolean-condition)// Or, if `boolean-condition` contains commas `,` not already within parenthesis `()`...BOOST_CONTRACT_ASSERT((boolean-condition))// ...use extra parenthesis (not a variadic macro).
This library will automatically call the failure handler boost::contract::check_failure
if any of the BOOST_CONTRACT_ASSERT
conditions are false or, more in general, if calling the implementation check
functor throws any exception. By default, this failure handler prints an
error message to std::cerr and terminates the program calling
std::terminate (see Throw
on Failures to change the failure handler to throw exceptions, exit
the program with an error code, etc.).
Similarly to the C-style assert
macro that is disabled when NDEBUG
is defined, implementation checks are disabled when BOOST_CONTRACT_NO_CHECKS
is defined (see Disable
Contract Checking). That will skip all implementation checks at run-time
but it will not eliminate some of the overhead of executing and compiling
the related boost::contract::check
declarations. Alternatively, this library provides the BOOST_CONTRACT_CHECK
macro that allows to completely remove run- and compile-time overheads of
implementation checks when BOOST_CONTRACT_NO_CHECKS
is defined (note that this is not a variadic macro):
BOOST_CONTRACT_CHECK(boolean-condition)// Or, if `boolean-condition` contains commas `,` not already within parenthesis `()`...BOOST_CONTRACT_CHECK((boolean-condition))// ...use extra parenthesis (not a variadic macro).
For example (see check_macro.cpp):
intmain(){// Implementation checks (via macro, disable run-/compile-time overhead).BOOST_CONTRACT_CHECK(gcd(12,28)==4);BOOST_CONTRACT_CHECK(gcd(4,14)==2);return0;}
The BOOST_CONTRACT_CHECK
macro is similar to the C-style assert macro as it accepts a boolean condition
(instead of a nullary functor like boost::contract::check
does).
Of course, nothing prevents programmers from calling functors within BOOST_CONTRACT_CHECK to specify
boolean conditions when if-guards and other statements are required to
assert the implementation checks. For example, programmers can use C++11
lambda functions to define and call such functors in place where the implementation
checks are specified:
BOOST_CONTRACT_CHECK([&]->bool{if(even_numbers)returngcd(x,y)==2;elsereturngcd(x,y)==3;}()); Using BOOST_CONTRACT_CHECK
is essentially equivalent to using the C-style assert
macro a part from the following:
Implementation checks are disabled defining BOOST_CONTRACT_NO_CHECKS
(instead of NDEBUG for
disabling assert).
If the asserted boolean condition is either false or it throws an exception
then this library will call boost::contract::check_failure
(instead assert calls
std::abort if the asserted condition is
false and it unwinds the stack if evaluating the condition throws an
exception).
Implementation checks are automatically disabled when other contract
conditions specified using this library are already being checked (to
avoid infinite recursion, see BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION).
Old
Values Copied at Body
In the examples seen so far, old value variables of type boost::contract::old_ptr
are initialized to a copy of the expression passed to BOOST_CONTRACT_OLDOF
as soon as they are declared. That correctly happens before the function
body is executed but also before the contract is declared, therefore even
before class invariants (for public functions) and preconditions are checked
at function entry. This might work well in most practical cases however,
technically speaking, old values should be copied before executing the function
body but after checking class invariants and preconditions
at function entry (see Assertions).
Specifically, there could be cases in which it makes sense to evaluate the
expressions passed to BOOST_CONTRACT_OLDOF
only under the assumption that assertions programmed in class invariants
and preconditions are true.
This library allows to construct boost::contract::old_ptr
variables using their default constructor (equivalent to a null pointer)
and then to later assign them to a copy of the expression specified by BOOST_CONTRACT_OLDOF in a nullary
functor d()
passed to .old(d). The functor d() is called by this library before the function
body is executed but only after class invariants and preconditions are checked.
Old value assignments via .old(...)
must appear after preconditions but before postconditions and exception guarantees
wen these are all present (see Preconditions,
Postconditions,
and Exception
Guarantees). Rationale: Functors for preconditions,
old value assignments, postconditions, and exception guarantees are all
optional but when specified, they must be specified in that order. Such
order is enforced by the fact that boost::contract::specify_precondition_old_postcondition_except,
boost::contract::specify_old_postcondition_except,
boost::contract::specify_postcondition_except,
boost::contract::specify_except,
and boost::contract::specify_nothing
provide a progressively smaller subset of their .precondition(...),
.old(...), .postcondition(...),
and .except(...) member functions. The enforced order
for specifying preconditions, old value assignments, postconditions, and
exception guarantees makes logical sense because it follows the order at
which these are executed at run-time. Other contract programming frameworks
allow to mix this order, that could have been implemented for this library
as well but it would have complicated somewhat the library implementation
while adding no real value (arguably creating confusion in user code by
not enforcing a consistent order for specifying contract conditions).
For example, the following old value expression s[index] passed to BOOST_CONTRACT_OLDOF
is valid only after the precondition has checked that index
is within the valid range index<s.size().
Therefore, old_char is first
declared using its default constructor (i.e., initialized to a null pointer)
and later assigned to a copy of s[index] in .old(...)
after the precondition has checked index
(see old.cpp):
charreplace(std::string&s,unsignedindex,charx){charresult;boost::contract::old_ptr<char>old_char;// Null, old value copied later...boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(index<s.size());}).old([&]{// ...after preconditions (and invariants) checked.old_char=BOOST_CONTRACT_OLDOF(s[index]);}).postcondition([&]{BOOST_CONTRACT_ASSERT(s[index]==x);BOOST_CONTRACT_ASSERT(result==*old_char);});result=s[index];s[index]=x;returnresult;}
The functor passed to .old(...) should capture all the variables that
it needs to evaluate the old value expressions passed to BOOST_CONTRACT_OLDOF.
In general, these variables should be captured by reference and not by value
(because old values need to copy the values the captured variables will have
just before executing the function body, and not the values these variables
had when the functor passed to .old(...)
was first declared). In any case, programmers should write the functor passed
to .old(...) so that it modifies only old values
and not the values of other captured variables, even when those are captured
by reference (see Constant-Correctness).
This library will automatically call the failure handler boost::contract::old_failure
if calling the functor specified via .old(...)
throws an exception (by default, this handler prints an error message to
std::cerr and terminates the program calling
std::terminate, but see Throw
on Failures to throw exceptions, exit the program with an error code,
etc.).
If old value pointers are initialized at the point of their construction
instead of using .old(...) then an exception thrown by the old
value expression passed to BOOST_CONTRACT_OLDOF,
or more in general any exception thrown by the old value pointer initialization,
will result in that exception being thrown up the stack by the enclosing
function. This is arguably less correct than calling boost::contract::old_failure
because an exception thrown by an old value copy causes the program to
fail to check its postconditions and exception guarantees but should not
automatically causes the enclosing function to thrown an exception (this
might not be a significant difference in practice, but it could be an additional
reason to use .old(...) instead of assigning old values when
they are declared before the contract). Rationale: It would be possible for
this library to internally wrap all old value operations (boost::contract::old_ptr copy
constructor, boost::contract::make_old,
etc.) with try-catch statements so to call boost::contract::old_failure
also when old values are copied when they are constructed outside .old(...). However, that will prevent this
library from knowing the boost::contract::from
parameter and that would be problematic (specifically because destructors
can have postconditions so that parameter is necessary to make sure user-defined
failure handlers can be programmed to never throw from destructors as
C++ usually requires).
Named Overrides
As seen in Public
Function Overrides, the BOOST_CONTRACT_OVERRIDE
macro has to be used to declare the type override_... that is passed as an explicit template
parameter to boost::contract::public_function
for public function overrides. The function names passed to BOOST_CONTRACT_OVERRIDE
(and BOOST_CONTRACT_OVERRIDES)
should never start with an underscore to avoid generating names containing
double underscores override__... (because all symbols containing double
underscores ...__... are reserved symbols in the C++ standard).
There is a separate macro BOOST_CONTRACT_NAMED_OVERRIDE
that can be used to explicitly specify the name of the type being declared:
Rationale: A different macro BOOST_CONTRACT_NAMED_OVERRIDE
is used instead of overloading BOOST_CONTRACT_OVERRIDE
using variadic macros because the override macro cannot be programmed manually
by users so making it a variadic would prevent to use this library on compilers
that do not support variadic macros (see No
Macros).
BOOST_CONTRACT_OVERRIDE(function-name)// Generate `override_...`.BOOST_CONTRACT_NAMED_OVERRIDE(type-name,function-name)// Generate `type-name`.
For example, the following public function override is named _1 so BOOST_CONTRACT_OVERRIDE(_1)
would declare a type named override__1
(which is reserved symbol in C++ because it contains a double underscore
__), thus BOOST_CONTRACT_NAMED_OVERRIDE(override1,_1)
is used to name the type override1
instead (see named_override.cpp):
template<typenameT>classpositive_unary_pack#defineBASESpublicgeneric_unary_pack<T>:BASES{public:typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASES// BOOST_CONTRACT_OVERRIDE(_1) would generate reserved name `override__1`.BOOST_CONTRACT_NAMED_OVERRIDE(override1,_1)// Generate `override1`.virtualvoid_1(Tconst&value,boost::contract::virtual_*v=0)/* override */{// Use `override1` generated by BOOST_CONTRACT_NAMED_OVERRIDE above.boost::contract::checkc=boost::contract::public_function<override1>(v,static_cast<void(positive_unary_pack::*)(Tconst&,boost::contract::virtual_*)>(&positive_unary_pack::_1),this,value).precondition([&]{BOOST_CONTRACT_ASSERT(value>0);});value1_=value;}/* ... */
The BOOST_CONTRACT_NAMED_OVERRIDE
macro can also be used when the name override_... generated by BOOST_CONTRACT_OVERRIDE
would clash with other names in user code, to generate names in CamelCase
or in any other preferred style, and in any other case when programmers need
or prefer to generate names different from override_....
Note that there is not a BOOST_CONTRACT_NAMED_OVERRIDES
macro so BOOST_CONTRACT_NAMED_OVERRIDE
needs to be invoked separately on each function name (there is instead a
BOOST_CONTRACT_OVERRIDES
macro as seen in Public
Function Overrides). Rationale: The syntax for invoking a possible
BOOST_CONTRACT_NAMED_OVERRIDES
macro would need to be something like BOOST_CONTRACT_NAMED_OVERRIDES(type_name1,func_name1,type_name2,func_name2,...).
The authors found such a syntax less readable than repeating single BOOST_CONTRACT_NAMED_OVERRIDE
invocations as in BOOST_CONTRACT_NAMED_OVERRIDE(type_name1,func_name1)BOOST_CONTRACT_NAMED_OVERRIDE(type_name2,func_name2)... so
decided not to provide the BOOST_CONTRACT_NAMED_OVERRIDES
macro.
Access Specifiers
As seen thus far, this library requires programmers to decorate their classes
declaring the following extra members:
The invariant and static_invariant member functions (used
to check class invariants, see Class
Invariants).
The base_types member
typedef declared via BOOST_CONTRACT_BASE_TYPES
(used to implement subcontracting, see Public
Function Overrides).
The override_...
member types declared via BOOST_CONTRACT_OVERRIDE,
BOOST_CONTRACT_NAMED_OVERRIDE,
and BOOST_CONTRACT_OVERRIDES
(used to implement subcontracting for overriding functions, see Public
Function Overrides). Rationale: Note that the internals
of the override_...
type generated by BOOST_CONTRACT_OVERRIDE
use names reserved by this library so programmers should not actually
use such a type even when it is declared public.
In general, these members must be declared public
in the user class in order for this library to be able to access them.
There is some variability among compiler implementations: The base_types member type needs to be declared
public on MSVC, GCC, and Clang;
The invariant and static_invariant member functions need
to be declared public on MSVC,
but not on GCC and Clang; The override_... member types do not have to be declared
public on any compiler. In
any case, declaring these extra members all public
or all private when the boost::contract::access class
is also declared friend always
works on all compilers.
However, programmers might need to more precisely control the
public members of their classes to prevent incorrect access of encapsulated
members. All these members can be declared private
as long as the boost::contract::access
class is declared as friend
of the user class. For example (see access.cpp):
template<typenameT>classvector#defineBASESpublicpushable<T>:BASES{// Private section of the class.friendclassboost::contract::access;// Friend `access` class so...typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// ...private bases.#undefBASESvoidinvariant()const{// ...private invariants.BOOST_CONTRACT_ASSERT(size()<=capacity());}BOOST_CONTRACT_OVERRIDE(push_back)// ...private overrides.public:// Public section of the class.voidpush_back(Tconst&value,boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<unsigned>old_size=BOOST_CONTRACT_OLDOF(v,size());boost::contract::checkc=boost::contract::public_function<override_push_back>(v,&vector::push_back,this,value).precondition([&]{BOOST_CONTRACT_ASSERT(size()<max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);});vect_.push_back(value);}/* ... */
This technique is not used in most examples of this documentation only for
brevity. Programmers are encouraged to use boost::contract::access
in real production code freely as they see fit.
Not declaring boost::contract::access
friend of user classes might cause compiler errors on some compilers (e.g.,
MSVC) because the private members needed to check the contracts will not
be accessible. On other compilers (e.g., GCC and Clang), the private access
level will instead fail SFINAE and no compiler error will be reported while
invariants and subcontracting will be silently skipped at run-time. Therefore,
programmers should always make sure to either declare invariant functions
and base types typedef as
public members or to declare boost::contract::access
as friend.
Throw
on Failures (and noexcept)
If a condition checked using BOOST_CONTRACT_ASSERT
is evaluated to be false or, more in general, if any of the specified contract
code throws an exception (BOOST_CONTRACT_ASSERT
simply expands to code that throws a boost::contract::assertion_failure
exception, see No
Macros), this library will call an appropriate contract
failure handler function as follow:
Preconditions: False BOOST_CONTRACT_ASSERT
assertions and exceptions thrown from within .precondition(...)
call boost::contract::precondition_failure.
Postconditions: False BOOST_CONTRACT_ASSERT
assertions and exceptions thrown from within .postcondition(...)
call boost::contract::postcondition_failure.
Exceptions guarantees: False BOOST_CONTRACT_ASSERT
assertions and exceptions thrown from within .except(...)
call boost::contract::except_failure.
Class invariants: False BOOST_CONTRACT_ASSERT
assertions and exceptions thrown from invariant() and static_invariant() call boost::contract::entry_invariant_failure
when checked at function entry and boost::contract::exit_invariant_failure
when checked at function exit.
Old values copied at body: Exceptions thrown from old values copied at
body within .old(...) call boost::contract::old_failure.
Implementation checks: False BOOST_CONTRACT_ASSERT
assertions and exceptions thrown from implementation checks boost::contract::checkc=nullary-functor
and BOOST_CONTRACT_CHECK(...) call boost::contract::check_failure.
By default, these contract failure handlers print a message to the standard
error std::cerr and then terminate the program calling
std::terminate. Rationale: In general, when a contract
fails the only safe thing to do is to terminate program execution (because
the contract failure indicates a bug in the program, and in general a buggy
program will be in a state for which no operation can be successfully and
safely performed, so the program should be stopped as soon as possible).
Therefore, this library terminates the program by default. However, for
specific applications, programmers could implement some fail-safe mechanism
for which some mission-critical operations could always be performed upon
handling failures so this library allows programmers to override the default
contract failure handlers to fully customize how to handle contract failures.
However, programmers can override the default contract failure
handlers to perform any custom action on contract failure using the following
functions respectively:
Preconditions: boost::contract::set_precondition_failure.
Postconditions: boost::contract::set_postcondition_failure.
Exception guarantees: boost::contract::set_except_failure.
Class invariants: boost::contract::set_entry_invariant_failure
and boost::contract::set_exit_invariant_failure,
or boost::contract::set_invariant_failure
(to set both entry and exit invariant failure handlers at once for convenience).
Old values copied at body: boost::contract::set_old_failure.
Implementation checks: boost::contract::set_check_failure.
These set_..._failure(f) function calls return a reference to the
contract failure handler functor f
that they take as input parameter (so they can be concatenated). Rationale: The set_..._failure
functions take a functor as parameter (to accept not just function pointers
but also lambdas, binds, etc.) and they return this same functor as result
so they can be concatenated (this interface is a bit different from std::set_terminate). The related get_..._failure functions can be used to query
the functors currently set as failure handlers (this interface is similar
to std::get_terminate).
For example (see throw_on_failure.cpp):
intmain(){boost::contract::set_precondition_failure(boost::contract::set_postcondition_failure(boost::contract::set_invariant_failure(boost::contract::set_old_failure([](boost::contract::fromwhere){if(where==boost::contract::from_destructor){// Shall not throw from C++ destructors.std::clog<<"ignored destructor contract failure"<<std::endl;}elsethrow;// Re-throw (assertion_failure, user-defined, etc.).}))));boost::contract::set_except_failure([](boost::contract::from){// Already an active exception so shall not throw another...std::clog<<"ignored exception guarantee failure"<<std::endl;});boost::contract::set_check_failure([]{// But now CHECK shall not be used in destructor implementations.throw;// Re-throw (assertion_failure, user-defined, etc.).});/* ... */
When programming custom failure handlers that trow exceptions instead of
terminating the program, programmers should be wary of the following:
In order to comply with C++ and STL exception safety, destructors should
never throw (in fact destructors are implicitly declared noexcept since C++11). This library passes
a boost::contract::from
parameter to the contract failure handlers for preconditions, postconditions,
class invariants, and old values copied at body (see boost::contract::precondition_failure,
boost::contract::postcondition_failure,
boost::contract::entry_invariant_failure,
boost::contract::exit_invariant_failure,
and boost::contract::old_failure
respectively). This boost::contract::from
parameter indicates if the contract failure occurred in a destructor,
constructor, or function call so programmers can use it to code custom
contract failure hander functions that never throw from destructors.
(In the example above, contract failures from destructors are simply
ignored even if that is probably never a safe thing to do in real production
code.)
C++ stack-unwinding will execute base class destructors even when the
derived class destructor trows an exception. Therefore, the contracts
of base class destructors will continue to be checked when contract failure
handlers are programmed to throw exceptions on contract failures from
destructors (yet another reason not to throw exceptions from destructors,
not even because of contract failures).
The contract failure handler for exception guarantees boost::contract::except_failure
should never throw (regardless of the value of its boost::contract::from
parameter) because when boost::contract::except_failure
is called there is already an active exception on the stack, the exception
that triggered the exception guarantees to be checked in the first place
(throwing an exception while there is already an active exception will
force program termination or lead to undefined behaviour in C++).
Implementation checks can appear in any code, including destructor implementation
code, so boost::contract::check_failure
should also never throw, or implementation checks should never be used
in destructors otherwise these destructors will throw (note that boost::contract::check_failure
does not provide the boost::contract::from
parameter so it is not possible to differentiate from implementation
checks failing from destructors instead than from other parts of the
code).
Programmers need to decide how to handle contract failures from destructors
when they write custom contract failure handlers that throw exceptions
instead of terminating the program (given that C++ and STL exception safety
rules requires destructors to never throw). This is not a simple dilemma
and it might be a good reason to terminate the program instead of throwing
exceptions when assertions fail in C++ (as this library and also C-style
assert do by default).
Throw
User-Defined Exceptions
Contract assertions can be programmed to throw boost::contract::assertion_failure
using BOOST_CONTRACT_ASSERT(condition) as we have seen so far (see No
Macros). Alternatively, contract assertions can be programmed to throw
any other exception (including user-defined exceptions) using code similar
to the following:
if(!condition)throwexception-object;
For example, the following precondition functor throws boost::contract::assertion_failure
(via BOOST_CONTRACT_ASSERT)
on its first assertion and the user-defined exception too_large_error
on its second assertion (both exceptions will cause this library to call
the customized boost::contract::precondition_failure
listed above which will in turn re-throw the exceptions up the stack, see
throw_on_failure.cpp):
structtoo_large_error{};template<unsignedMaxSize>classcstring#defineBASESprivateboost::contract::constructor_precondition<cstring<\MaxSize>>:BASES{public:/* implicit */cstring(charconst*chars):boost::contract::constructor_precondition<cstring>([&]{BOOST_CONTRACT_ASSERT(chars);// Throw `assertion_failure`.// Or, throw user-defined exception.if(std::strlen(chars)>MaxSize)throwtoo_large_error();}){/* ... */};Exception
Specifiers (noexcept and throw`)
Exception specifiers noexcept
(since C++11) and throw (deprecated
in C++11) of the enclosing function, constructor, or destructor declaring
the contract correctly apply to the contract code as well. Therefore, even
if the contract failure handlers are reprogrammed to throw exceptions in
case of contract failures, those exceptions will never be thrown outside
the context of the enclosing operation if that is not in accordance with
the exception specifiers of that operation (specifically, note that all destructors
are implicitly declared noexcept
in C++11).
For example, the following code will correctly never throw from the noexcept destructor, not even if the class
invariants checked at destructor entry throw too_large_error
and the contract failure handlers for invariants are programmed to throw
from destructors (the program will always terminate in this case instead,
see throw_on_failure.cpp):
structtoo_large_error{};template<unsignedMaxSize>classcstring#defineBASESprivateboost::contract::constructor_precondition<cstring<\MaxSize>>:BASES{public:voidinvariant()const{if(size()>MaxSize)throwtoo_large_error();// Throw user-defined ex.BOOST_CONTRACT_ASSERT(chars_);// Or, throw `assertion_failure`.BOOST_CONTRACT_ASSERT(chars_[size()]=='\0');}~cstring()noexcept{// Exception specifiers apply to contract code.// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* ... */};/* ... */// Warning... might cause destructors to throw (unless declared noexcept).boost::contract::set_invariant_failure([](boost::contract::from){throw;// Throw no matter if from destructor, etc.});/* ... */Extras
This section can be consulted selectively for specific topics of interest.
Old
Value Requirements (Templates)
Old values require to copy the expression passed to BOOST_CONTRACT_OLDOF
thus the type of that expression needs to be copyable. More precisely, dereferencing
an old value pointer of type boost::contract::old_ptr<T>
requires boost::contract::is_old_value_copyable<T>::value to be true,
otherwise this library will generate a compile-time error.
In some cases it might be acceptable, or even desirable, to cause a compile-time
error when a program uses old value types that are not copyable (because
it is not possible to fully check the correctness of the program as stated
by the contract assertions that use these old values). In these cases, programmers
can declare old values using boost::contract::old_ptr
as seen so far.
However, in some other cases it might be desirable to simply skip assertions
that use old values when the respective old value types are not copyable,
without causing compile-time errors. Programmers can do this using boost::contract::old_ptr_if_copyable
instead of boost::contract::old_ptr
and checking if the old value pointer is not null before dereferencing it
in postconditions. For example, consider the following function template
that could in general be instantiated for types T
that are not copy constructible (that is for which boost::contract::is_old_value_copyable<T>::value is false,
see old_if_copyable.cpp):
Rationale: [N1962]
and other proposals to add contracts to C++ do not provide a mechanism
to selectively disable copies only for old value types that are not copy
constructible. However, this library provides such a mechanism to allow
to program contracts for template code without necessarily adding extra
copy constructible type requirements that would not be present if it were
not for copying old values (so compiling the code with and without contracts
will not necessarily alter the type requirements of the program). Something
similar could be achieved combing C++17 ifconstexpr with [N1962]
or [P0380] so that old value expressions
within template code can be guarded by ifconstexpr statements checking if
the old value types are copyable or not. For example, assuming old values
are added to [P0380] (using some kind
of oldof(...)
syntax) and that C++17 ifconstexpr can be used within [P0380]
contracts:
template<typenameT>voidoffset(T&x,intcount)[[ensures:ifconstexpr(std::is_copy_constructible<T>::value)x==oldof(x)+count]]...template<typenameT>// T might or might not be copyable.voidoffset(T&x,intcount){// No compiler error if T has no copy constructor...boost::contract::old_ptr_if_copyable<T>old_x=BOOST_CONTRACT_OLDOF(x);boost::contract::checkc=boost::contract::function().postcondition([&]{// ...but old value null if T has no copy constructor.if(old_x)BOOST_CONTRACT_ASSERT(x==*old_x+count);});x+=count;}
The old value pointer old_x
is programmed using boost::contract::old_ptr_if_copyable.
When T is copyable, boost::contract::old_ptr_if_copyable<T>
behaves like boost::contract::old_ptr<T>.
When T is not copyable instead,
boost::contract::old_ptr_if_copyable<T>
will simply not copy x at
run-time and leave old_x
initialized to a null pointer. Therefore, boost::contract::old_ptr_if_copyable
objects like old_x must be
checked to be not null as in if(old_x)... before
they are dereferenced in postconditions and exception guarantees (to avoid
run-time errors of dereferencing null pointers).
If the above example used boost::contract::old_ptr
instead then this library would have generated a compile-time error when
offset is instantiated with
types T that are not copy
constructible (but only if old_x
is actually dereferenced somewhere, for example in the contract assertions
using *old_x... or old_x->...).
Technically, on C++17 it is possible to use boost::contract::old_ptr
together with ifconstexpr
instead of using boost::contract::old_ptr_if_copyable,
for example:
template<typenameT>voidoffset(T&x,intcount){boost::contract::old_ptr<T>old_x;ifconstexpr(boost::contract::is_old_value_copyable<T>::value)old_x=BOOST_CONTRACT_OLDOF(x);boost::contract::checkc=boost::contract::function().postcondition([&]{ifconstexpr(boost::contract::is_old_value_copyable<T>::value)BOOST_CONTRACT_ASSERT(x==*old_x+count);});x+=count;}
However, the authors find this code less readable and more verbose than
its equivalent that uses boost::contract::old_ptr_if_copyable.
Guarding old value copies and related assertions with ifconstexpr is useful instead when
the guard condition checks type requirements more complex than just boost::contract::is_old_value_copyable
(as shown later in this documentation).
When C++11 auto declarations
are used with BOOST_CONTRACT_OLDOF,
this library always defaults to using the boost::contract::old_ptr
type (because its type requirements are more stringent than boost::contract::old_ptr_if_copyable).
For example, the following statements are equivalent:
autoold_x=BOOST_CONTRACT_OLDOF(x);// C++11 auto declarations always use `old_ptr` (never `old_ptr_if_copyable`).boost::contract::old_ptr<decltype(x)>old_x=BOOST_CONTRACT_OLDOF(x);
If programmers want to relax the copyable type requirement, they must do
so explicitly by using the boost::contract::old_ptr_if_copyable
type instead of using auto declarations.
Old
Value Type Traits
This library uses boost::contract::is_old_value_copyable
to determine if an old value type is copyable or not, and then boost::contract::old_value_copy
to actually copy the old value.
By default, boost::contract::is_old_value_copyable<T>
is equivalent to boost::is_copy_constructible<T> and
boost::contract::old_value_copy<T>
is implemented using T's
copy constructor. However, these type traits can be specialized by programmers
for example to avoid making old value copies of types even when they have
a copy constructor (maybe because these copy constructors are too expensive),
or to make old value copies for types that do not have a copy constructor,
or for any other specific need programmers might have for the types in question.
For example, the following specialization of boost::contract::is_old_value_copyable
intentionally avoids making old value copies for all expressions of type
w even if that type has a
copy constructor (see old_if_copyable.cpp):
// Copyable type but...classw{public:w(wconst&){/* Some very expensive copy operation here... */}/* ... */// ...never copy old values for type `w` (because its copy is too expensive).namespaceboost{namespacecontract{template<>structis_old_value_copyable<w>:boost::false_type{};}}
On the flip side, the following specializations of boost::contract::is_old_value_copyable
and boost::contract::old_value_copy
make old value copies of expressions of type p
even if that type does not actually have a copy constructor (see old_if_copyable.cpp):
// Non-copyable type but...classp:privateboost::noncopyable{int*num_;friendstructboost::contract::old_value_copy<p>;/* ... */// ...still copy old values for type `p` (using a deep copy).namespaceboost{namespacecontract{template<>structold_value_copy<p>{explicitold_value_copy(pconst&old){*old_.num_=*old.num_;// Deep copy pointed value.}pconst&old()const{returnold_;}private:pold_;};template<>structis_old_value_copyable<p>:boost::true_type{};}}
In general, boost::is_copy_constructible and therefore boost::contract::is_old_value_copyable
require C++11 decltype and SFINAE
to automatically detect if a given type is copyable or not. On non-C++11
compilers, it is possible to inherit the old value type from boost::noncopyable, or use BOOST_MOVABLE_BUT_NOT_COPYABLE,
or specialize boost::is_copy_constructible (see boost::is_copy_constructible documentation
for more information), or just specialize boost::contract::is_old_value_copyable.
For example, for a non-copyable type n
the following code will work also on non-C++11 compilers (see old_if_copyable.cpp):
classn{// Do not want to use boost::noncopyable but...intnum_;private:n(nconst&);// ...unimplemented private copy constructor (so non-copyable)./* ... */// Specialize `boost::is_copy_constructible` (no need for this on C++11).namespaceboost{namespacecontract{template<>structis_old_value_copyable<n>:boost::false_type{};}}Assertion
Requirements (Templates)
In general, assertions can introduce a new set of requirements on the types
used by the program. Some of these type requirements might be necessary only
to check the assertions and they would not be required by the program otherwise.
In some cases it might be acceptable, or even desirable, to cause a compile-time
error when a program uses types that do not provide all the operations needed
to check contract assertions (because it is not possible to fully check the
correctness of the program as specified by its contracts). In these cases,
programmers can specify contract assertions as we have seen so far, compilation
will fail if user types do not provide all operations necessary to check
the contracts.
However, in some other cases it might be desirable to not augment the type
requirements of a program just because of contract assertions and to simply
skip assertions when user types do not provide all the operations necessary
to check them, without causing compile-time errors. Programmers can do this
using ifconstexpr
on C++17 compilers, and boost::contract::condition_if
(or boost::contract::condition_if_c)
on non-C++17 compilers.
For example, let's consider the following vector<T>
class template equivalent to std::vector<T>.
C++ std::vector<T> does
not require that its value type parameter T
has an equality operator ==
(it only requires T to be
copy constructible, see std::vector
documentation). However, the contracts for the vector<T>::push_back(value)
public function include a postcondition back()==value
that introduces the new requirement that T
must also have an equality operator ==.
Programmers can specify this postcondition as usual with BOOST_CONTRACT_ASSERT(back()==value) an let the program fail to compile when
users instantiate vector<T>
with a type T that does not
provide an equality operator ==.
Otherwise, programmers can guard this postcondition using C++17 ifconstexpr
to evaluate the asserted condition only for types T
that have an equality operator ==
and skip it otherwise. Rationale: [N1962]
and other proposals to add contracts to C++ do not provide a mechanism
to selectively disable assertions based on their type requirements. However,
this library provides such a mechanism to allow to program contracts for
template code without necessarily adding extra type requirements that would
not be present if it was not for the contracts (so compiling the code with
and without contracts will not alter the type requirements of the program).
Something similar could be achieved combing C++17 ifconstexpr with [N1962]
or [P0380] so that contract assertions
within template code could be guarded by ifconstexpr statements checking the
related type requirements ([N1962]
already allows of if statements
in contracts under the name of select assertions,
[P0380] does not so probably if statements should be added to [P0380]
as well). For example, assuming C++17 ifconstexpr can be used within [P0380] contracts:
template<typenameT>classvector{public:voidpush_back(Tconst&value)[[ensures:ifconstexpr(boost::has_equal_to<T>::value)back()==value]]...}; For example:
template<typenameT>classvector{public:voidpush_back(Tconst&value){boost::contract::checkc=boot::contract::public_function(this).postcondition([&]{// Guard with `if constexpr` for T without `==`.ifconstexpr(boost::has_equal_to<T>::value)BOOST_CONTRACT_ASSERT(back()==value);});vect_.push_back(value);}/* ... */
More in general, ifconstexpr
can be used to guard a mix of both old value copies and contract assertions
that introduce specific extra type requirements. For example, the following
swap function can be called
on any type T that is movable
but its old value copies and postcondition assertions are evaluated only
for types T that are also
copyable and have an equality operator ==
(see if_constexpr.cpp):
template<typenameT>voidswap(T&x,T&y){constexprboolb=boost::contract::is_old_value_copyable<T>::value&&boost::has_equal_to<T>::value;boost::contract::old_ptr<T>old_x,old_y;ifconstexpr(b){// Contract requires copyable T...old_x=BOOST_CONTRACT_OLDOF(x);old_y=BOOST_CONTRACT_OLDOF(y);}boost::contract::checkc=boost::contract::function().postcondition([&]{ifconstexpr(b){// ... and T with `==`...BOOST_CONTRACT_ASSERT(x==*old_y);BOOST_CONTRACT_ASSERT(y==*old_x);}});Tt=std::move(x);// ...but body only requires movable T.x=std::move(y);y=std::move(t);}No
ifconstexpr
(no C++17)
On non-C++17 compilers where ifconstexpr is not available, it is possible
to use boost::contract::condition_if
to skip assertions based on type requirements (even if this code is less
readable and more verbose than using ifconstexpr). For example (see condition_if.cpp):
template<typenameT>classvector{public:voidpush_back(Tconst&value){boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Instead of `ASSERT(back() == value)` for T without `==`.BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<T>(),boost::cref(back()),boost::cref(value))));});vect_.push_back(value);}/* ... */
More in general, boost::contract::condition_if
is used as follow:
boost::contract::condition_if<Pred>(cond)
Where Pred is a nullary boolean
meta-function and cond is
a nullary boolean functor. If Pred::value
is statically evaluated to be true
at compile-time then cond() is called at run-time and its boolean result
is returned by the enclosing boost::contract::condition_if
call. Otherwise, if Pred::value
is statically evaluated to be false
at compile-time then boost::contract::condition_if
trivially returns true. Therefore,
if cond is a functor template
instantiation (not just a functor) then its call that contains the assertion
operations with the extra type requirements (e.g., the equality operator
==) will not be actually instantiated
and compiled unless the compiler determines at compile-time that Pred::value is true
(when used this way, functor templates like std::equal_to
and C++14 generic lambdas can be used to program cond,
but C++11 lambdas cannot).
The boost::contract::condition_if
function template is a special case of the more general boost::contract::call_if,
specifically boost::contract::condition_if<Pred>(cond) is logically equivalent to boost::contract::call_if<Pred>(cond).else_([]{returntrue;}).
The internal implementation of boost::contract::condition_if
is optimized and it does not actually use boost::contract::call_if.
The boost::contract::call_if
function template also accepts a number of optional else-if
statements and one optional else statement:
boost::contract::call_if<Pred1>(t1).templateelse_if<Pred2>(// Optional.t2)...// Optionally, other `else_if` statements..else_(// Optional for `void` functors, otherwise required.e)
Where Pred1, Pred2, ... are nullary boolean meta-functions
and t1, t2,
..., e are nullary functors.
The return types of the functor calls t1(), t2(), ..., e() must either be all the same (including
possibly all void) or be of
types implicitly convertible into one another. At run-time boost::contract::call_if will
call the functor t1(),
or t2(),
..., or e()
depending on which meta-function Pred1::value,
Pred2::value, ... is statically evaluated to be
true or false
at compile-time, and it will return the value returned by the functor being
called. If t1, t2, ..., e
are functor template instantiations (not just functors) then their code will
only be compiled if the compiler determines they need to be actually called
at run-time (so only if the related Pred1::value,
Pred2::value, ... are respectively evaluated to
be true or false
at compile-time). All the else_if<...>(...) statements are optional.
The else_(...)
statement is optional if the functor calls return void,
otherwise it is required.
In general, boost::contract::call_if
can be used to program contract assertions that compile and check different
functor templates depending on related predicates being statically evaluated
to be true or false at compile-time (but in most cases
boost::contract::condition_if
should be sufficient and less verbose to use). The boost::contract::condition_if_c,
boost::contract::call_if_c,
and .else_if_c
function templates work similarly to their counterparts without the ..._c postfix
seen so far, but they take their predicate template parameters as static
boolean values instead of nullary boolean meta-functions.
On compilers that support C++17 ifconstexpr there should be no need
to use boost::contract::condition_if
or boost::contract::call_if
because ifconstexpr
can be used instead (making the code more readable and easier to program).
A part from its use within contracts, boost::contract::call_if
can be used together with C++14 generic lambdas to emulate C++17 ifconstexpr
(boost::hana::if_ and probably other approaches can
also be used together with generic lambdas to emulate C++17 ifconstexpr
on C++14 compilers). For example, the following implementation of myadvance will compile since C++14
and it is more concise, easier to read and maintain than the usual implementation
of std::advance that uses tag dispatching (see
call_if_cxx14.cpp):
template<typenameIter,typenameDist>voidmyadvance(Iter&i,Distn){Iter*p=&i;// So captures change actual pointed iterator value.boost::contract::call_if<is_random_access_iterator<Iter>>(std::bind([](autop,auton){// C++14 generic lambda.*p+=n;},p,n)).templateelse_if<is_bidirectional_iterator<Iter>>(std::bind([](autop,auton){if(n>=0)while(n--)++*p;elsewhile(n++)--*p;},p,n)).templateelse_if<is_input_iterator<Iter>>(std::bind([](autop,auton){while(n--)++*p;},p,n)).else_(std::bind([](autofalse_){static_assert(false_,"requires at least input iterator");},std::false_type())// Use constexpr value.);}
Of course, since C++17 the implementation that uses ifconstexpr is even more readable
and concise:
template<typenameIter,typenameDist>voidmyadvance(Iter&i,Distn){ifconstexpr(is_random_access_iterator<Iter>::value){i+=n;}elseifconstexpr(is_bidirectional_iterator<Iter>::value){if(n>=0)while(n--)++i;elsewhile(n++)--i;}elseifconstexpr(is_input_iterator<Iter>::value){while(n--)++i;}else{static_assert(false,"requires at least input iterator");}}Volatile
Public Functions
This library allows to specify a different set of class invariants to check
for volatile public functions. These volatile class invariants
are programmed in a public constvolatile function, named invariant,
taking no argument, and returning void
(see BOOST_CONTRACT_INVARIANT_FUNC
to name the invariant function differently from invariant
and Access Specifiers
to not have to declare it public).
Classes that do no have invariants for their volatile public functions, simply
do not declare the voidinvariant()constvolatile function.
In general, constvolatile
invariants work the same as const
invariants (see Class
Invariants) with the only difference that volatile
and constvolatile
functions check constvolatile
invariants while non-const (i.e.,
neither const nor volatile) and const
functions check const invariants.
A given class can specify any combination of static,
constvolatile,
and const invariant functions
(see Class Invariants):
Rationale: Constructors and destructors
check constvolatile
and const invariants in that
order because the qualifier that can be applied to more calls is checked
first (note that constvolatile
calls can be made on any object while const
calls cannot be made on volatile
objects, in that sense the constvolatile qualifier can be applied
to more calls than const alone
can). This is consistent with static
class invariants that are checked even before constvolatile invariants (the static classifier can be applied to even
more calls than constvolatile,
in fact an object is not even needed to make static calls).
Constructors check static
invariants at entry and exit (even if an exception is thrown), plus
constvolatile
and const invariants in
that order at exit but only if no exception is thrown.
Destructors check static
invariants at entry and exit (even if an exception is thrown), plus
constvolatile
and const invariants in
that order at entry (and at exit but only if an exception is thrown,
even is destructors should in general never throw in C++).
Both non-const and const public functions check static and const
invariants at entry and at exit (even if an exception is thrown).
Both volatile and constvolatile
public functions check static
and constvolatile
invariants at entry and at exit (even if an exception is thrown).
These rules ensure that volatile class invariants are correctly checked (see
Constructor
Calls, Destructor
Calls, and Public
Function Calls). For example (see volatile.cpp):
classu{public:staticvoidstatic_invariant();// Static invariants.voidinvariant()constvolatile;// Volatile invariants.voidinvariant()const;// Const invariants.u(){// Check static, volatile, and const invariants.boost::contract::checkc=boost::contract::constructor(this);}~u(){// Check static, volatile, and const invariants.boost::contract::checkc=boost::contract::destructor(this);}voidnc(){// Check static and const invariants.boost::contract::checkc=boost::contract::public_function(this);}voidc()const{// Check static and const invariants.boost::contract::checkc=boost::contract::public_function(this);}voidv()volatile{// Check static and volatile invariants.boost::contract::checkc=boost::contract::public_function(this);}voidcv()constvolatile{// Check static and volatile invariants.boost::contract::checkc=boost::contract::public_function(this);}staticvoids(){// Check static invariants only.boost::contract::checkc=boost::contract::public_function<u>();}};
This library does not automatically check constvolatile invariants for non-volatile functions. However, if the contract
specifications require it, programmers can explicitly call the constvolatile
invariant function from the const
invariant function (preferably in that order to be consistent with the order
constvolatile
and const invariants are checked
for constructors and destructors). That way all public functions, volatile or not, will check constvolatile
invariants (while only const
and non-const public functions
will check only const invariants,
correctly so because the volatile
qualifier shall not be stripped away): Rationale: Note that while all public
functions can be made to check constvolatile invariants, it is never
possible to make volatile public functions check const
non-volatile invariants. That is because both const
and volatile can always be
added but never stripped in C++ (a part from forcefully via const_cast) but const
is always automatically added by this library in order to enforce contract
constant-correctness (see Constant-Correctness).
That said, it would be too stringent for this library to also automatically
add volatile and require all
functions to check constvolatile (not just const)
invariants because only volatile
members can be accessed from constvolatile invariants so there could
be many const (but not constvolatile)
members that are accessible from const
invariants but not from constvolatile invariants. To avoid this confusion,
this library has chosen to draw a clear dichotomy between const and constvolatile invariants so that only
volatile public functions check constvolatile invariants and only non-volatile
public functions check const
(but not constvolatile)
invariants. This is a clear distinction and it should serve most cases.
If programmers need non-volatile public functions to also check constvolatile
invariants, they can explicitly do so by calling the constvolatile invariant function from
the const invariant function
as shown in this documentation.
classu{public:voidinvariant()constvolatile{...}// Volatile invariants.voidinvariant()const{autoconstvolatile*cv=this;cv->invariant();// Call `const volatile` invariant function above....// Other non-volatile invariants.}...};
(As usual, private and protected functions do not check any invariant, not
even when they are volatile
or constvolatile,
see Private
and Protected Functions).
Move Operations
As with all public operations of a class, also public move operations should
maintain class invariants (see [Stroustrup13],
p. 520). Specifically, at a minimum C++ requires the following:
The moved-from object can be copy assigned.
The moved-from object can be move assigned.
The moved-from object can be destroyed (if not for any other reason,
this requires that class invariants are maintained by move operations
because the destructor of the moved-from object requires class invariants
to be satisfied at its entry, as always with destructors see Destructor
Calls).
Therefore, both the move constructor and the move assignment operator need
to maintain the class invariants of the moved-from object so their contracts
can be programmed using boost::contract::constructor
and boost::contract::public_function
as usual. For example (see move.cpp):
classcircular_buffer:privateboost::contract::constructor_precondition<circular_buffer>{public:voidinvariant()const{if(!moved()){// Do not check (some) invariants for moved-from objects.BOOST_CONTRACT_ASSERT(index()<size());}// More invariants here that hold also for moved-from objects (e.g.,// all assertions necessary to successfully destroy moved-from objects).}// Move constructor.circular_buffer(circular_buffer&&other):boost::contract::constructor_precondition<circular_buffer>([&]{BOOST_CONTRACT_ASSERT(!other.moved());}){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(!moved());BOOST_CONTRACT_ASSERT(other.moved());});move(std::forward<circular_buffer>(other));}// Move assignment.circular_buffer&operator=(circular_buffer&&other){// Moved-from can be (move) assigned (so no pre `!moved()` here).boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!other.moved());}).postcondition([&]{BOOST_CONTRACT_ASSERT(!moved());BOOST_CONTRACT_ASSERT(other.moved());});returnmove(std::forward<circular_buffer>(other));}~circular_buffer(){// Moved-from can always be destroyed (in fact no preconditions).boost::contract::checkc=boost::contract::destructor(this);}boolmoved()const{boost::contract::checkc=boost::contract::public_function(this);returnmoved_;}private:boolmoved_;/* ... */
This example assumes that it is possible to call the public function moved()
on the moved-from object.
In this example, the moved() function is simple enough that programmers
could decide to not even call boost::contract::public_function
from it for optimization reasons. However, calling boost::contract::public_function
from moved()
has no negative impact, a part from run-time overhead, because this library
automatically disables contract checking while checking other contracts
(so this call will not cause infinite recursion).
The default move constructor and move assignment operator generated by
C++ will not automatically check contracts. Therefore, unless the move
operations are not public or they have no preconditions, no postconditions,
and their class has no invariants, programmers should manually define them
using boost::contract::constructor,
boost::contract::constructor_precondition,
and boost::contract::public_function
instead of relying on their default implementations generated by C++. (Same
as for all other operations automatically implemented by C++.)
As always, programmers can decide to not program contracts for a given type.
Specifically, they might decide to not program contracts for a class that
needs to be moved in order to avoid the run-time overhead of checking contract
assertions and to maximize performance (see Benefits
and Costs).
Unions
A C++ union cannot have virtual
functions, base classes, and cannot be used as a base class thus subcontracting
(boost::contract::virtual_,
BOOST_CONTRACT_OVERRIDE,
etc.) do not apply to unions. Also a union
cannot inherit from boost::contract::constructor_precondition
(because it cannot have base classes), instead boost::contract::constructor_precondition
is used to declare a local object that checks constructor preconditions (at
the very beginning of the constructor before old value copies and other contracts,
see declaration of pre in
the example below). A part from that, this library is used as usual to program
contracts for unions. For example (see union.cpp):
unionpositive{public:staticvoidstatic_invariant(){// Static class invariants (as usual).BOOST_CONTRACT_ASSERT(instances()>=0);}voidinvariant()const{// Class invariants (as usual).BOOST_CONTRACT_ASSERT(i_>0);BOOST_CONTRACT_ASSERT(d_>0);}// Contracts for constructor, as usual but...explicitpositive(intx):d_(0){// ...unions cannot have bases so constructor preconditions here.boost::contract::constructor_precondition<positive>pre([&]{BOOST_CONTRACT_ASSERT(x>0);});boost::contract::old_ptr<int>old_instances=BOOST_CONTRACT_OLDOF(instances());boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{{inty;get(y);BOOST_CONTRACT_ASSERT(y==x);}BOOST_CONTRACT_ASSERT(instances()==*old_instances+1);});i_=x;++instances_;}// Contracts for destructor (as usual).~positive(){boost::contract::old_ptr<int>old_instances=BOOST_CONTRACT_OLDOF(instances());boost::contract::checkc=boost::contract::destructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(instances()==*old_instances-1);});--instances_;}// Contracts for public function (as usual, but no virtual or override).voidget(int&x)const{boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(x>0);});x=i_;}// Contracts for static public function (as usual).staticintinstances(){boost::contract::checkc=boost::contract::public_function<positive>();returninstances_;}private:inti_;doubled_;/* ... */Assertion Levels
This library provides three predefined assertion levels
that can be used to selectively disable assertions depending on their computational
complexity:
The assertion levels predefined by this library are similar to the default,
audit, and axiom levels from [P0380].
BOOST_CONTRACT_ASSERT
is used to assert conditions that are not computationally expensive,
at least compared to the cost of executing the function body. These assertions
are the ones we have seen so far, they are always checked at run-time
and they cannot be disabled.
BOOST_CONTRACT_ASSERT_AUDIT
is used to assert conditions that are computationally expensive compared
to the cost of executing the function body. These assertions are not
checked at run-time unless programmers explicitly define BOOST_CONTRACT_AUDITS
(undefined by default), but the asserted conditions are always compiled
and therefore validated syntactically (even when they are not actually
evaluated and checked at run-time).
BOOST_CONTRACT_ASSERT_AXIOM
is used to assert conditions that are computationally prohibitive, at
least compared to the cost of executing the function body. These assertions
are never evaluated or checked at run-time, but the asserted conditions
are always compiled and therefore validated syntactically (so these assertions
can serve as formal comments to the code).
In addition, BOOST_CONTRACT_CHECK_AUDIT
and BOOST_CONTRACT_CHECK_AXIOM
are similar to BOOST_CONTRACT_ASSERT_AUDIT
and BOOST_CONTRACT_ASSERT_AXIOM
but they are used to program audit and axiom levels for implementation checks
instead of assertions (see Implementation
Checks).
For example, BOOST_CONTRACT_ASSERT_AUDIT
can be used to program computationally expensive assertions (see assertion_level.cpp):
template<typenameRandomIter,typenameT>RandomIterrandom_binary_search(RandomIterfirst,RandomIterlast,Tconst&value){RandomIterresult;boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(first<=last);// Default, not expensive.// Expensive O(n) assertion (use AXIOM if prohibitive instead).BOOST_CONTRACT_ASSERT_AUDIT(std::is_sorted(first,last));}).postcondition([&]{if(result!=last)BOOST_CONTRACT_ASSERT(*result==value);});/* ... */
Similarly, BOOST_CONTRACT_AUDITS
can be used to disable expensive old value copies and related assertions
that use them (see assertion_level.cpp):
template<typenameT>classvector{public:voidswap(vector&other){boost::contract::old_ptr<vector>old_me,old_other;#ifdefBOOST_CONTRACT_AUDITSold_me=BOOST_CONTRACT_OLDOF(*this);old_other=BOOST_CONTRACT_OLDOF(other);#endif// Else, skip old value copies...boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// ...and also skip related assertions.BOOST_CONTRACT_ASSERT_AUDIT(*this==*old_other);BOOST_CONTRACT_ASSERT_AUDIT(other==*old_me);});vect_.swap(other.vect_);}/* ... */private:std::vector<T>vect_;};
The condition passed to BOOST_CONTRACT_ASSERT_AXIOM
is compiled but not actually evaluated at run-time so this macro can be used
to program computationally prohibitive assertions but also assertions that
cannot actually be programmed in C++ using functions that are declared but
left undefined. For example, (see assertion_level.cpp):
// If valid iterator range (cannot implement in C++ but OK to use in AXIOM).template<typenameIter>boolvalid(Iterfirst,Iterlast);// Only declared, not actually defined.template<typenameT>classvector{public:iteratorinsert(iteratorwhere,Tconst&value){iteratorresult;boost::contract::old_ptr<unsigned>old_capacity=BOOST_CONTRACT_OLDOF(capacity());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()>=*old_capacity);if(capacity()>*old_capacity){BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(),end()));}else{BOOST_CONTRACT_ASSERT_AXIOM(!valid(where,end()));}});returnresult=vect_.insert(where,value);}/* ... */private:std::vector<T>vect_;};
In addition to these assertion levels that are predefined by this library,
programmers are free to define their own. For example, the following macro
could be used to program and selectively disable assertions that have exponential
computational complexity O(e^n):
#ifdefEXPONENTIALLY_COMPLEX_ASSERTIONS// Following will compile and also evaluate `cond`.#defineASSERT_EXP(cond)BOOST_CONTRACT_ASSERT(cond)#else// Following will compile but never actually evaluate `cond`.#defineASSERT_EXP(cond)BOOST_CONTRACT_ASSERT(true||(cond))#endif...ASSERT_EXP(some-exponentially-complex-boolean-condition);Disable
Contract Checking
Checking contracts adds run-time overhead and can slow down program execution
(see Benefits
and Costs). Therefore, programmers can define any combination of the
following macros (-D
option in Clang and GCC, /D
option in MSVC, etc.) to instruct this library to not check specific groups
of contract conditions at run-time:
Define BOOST_CONTRACT_NO_PRECONDITIONS
to not check preconditions.
Define BOOST_CONTRACT_NO_POSTCONDITIONS
to not check postconditions.
Define BOOST_CONTRACT_NO_EXCEPTS
to not check exception guarantees.
Define BOOST_CONTRACT_NO_ENTRY_INVARIANTS
to not check class invariants at call entry.
Define BOOST_CONTRACT_NO_EXIT_INVARIANTS
to not check class invariants at call exit.
Or, define BOOST_CONTRACT_NO_INVARIANTS
to not check class invariants at both call entry and exit. (This is provided
for convenience, it is equivalent to defining both BOOST_CONTRACT_NO_ENTRY_INVARIANTS
and BOOST_CONTRACT_NO_EXIT_INVARIANTS.)
Define BOOST_CONTRACT_NO_CHECKS
to not evaluate implementation checks.
Old values can be used by both postconditions and exception guarantees
so it is necessary to define both BOOST_CONTRACT_NO_POSTCONDITIONS
and BOOST_CONTRACT_NO_EXCEPTS
to disable old value copies.
By default, none of these macros are defined so this library checks all contracts.
When these macros are defined by the user, the implementation code of this
library is internally optimized to minimize as much as possible any run-time
and compile-time overhead associated with checking and compiling contracts
(see Disable
Contract Compilation for techniques to completely remove any run-time
and compile-time overheads associated with contract code).
For example, programmers could decide to check all contracts during early
development builds, but later check only preconditions and maybe entry invariants
for release builds by defining BOOST_CONTRACT_NO_POSTCONDITIONS,
BOOST_CONTRACT_NO_EXCEPTS,
BOOST_CONTRACT_NO_EXIT_INVARIANTS,
and BOOST_CONTRACT_NO_CHECKS.
Disable
Contract Compilation (Macro Interface)
This library provides macros that can be used to completely disable compile-time
and run-time overhead introduced by contracts but at the cost of manually
programming #ifndefBOOST_CONTRACT_NO_... statements around contract code:
This library defines BOOST_CONTRACT_NO_CONSTRUCTORS
when contract checking is disabled for constructors.
This library defines BOOST_CONTRACT_NO_DESTRUCTORS
when contract checking is disabled for destructors.
This library defines BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
when contract checking is disabled for public functions.
This library defines BOOST_CONTRACT_NO_FUNCTIONS
when contract checking is disabled for (non-public and non-member) functions.
This library defines BOOST_CONTRACT_NO_OLDS
when old value copies are disabled.
This library defines BOOST_CONTRACT_NO_ALL
when all contracts above and also implementation checks (see BOOST_CONTRACT_NO_CHECKS)
are disabled.
These macros are not configuration macros and they should not be defined
directly by programmers (otherwise this library will generate compile-time
errors). Instead, these macros are automatically defined by this library
when programmers define BOOST_CONTRACT_NO_PRECONDITIONS,
BOOST_CONTRACT_NO_POSTCONDITIONS,
BOOST_CONTRACT_NO_EXCEPTS,
BOOST_CONTRACT_NO_INVARIANTS
(or BOOST_CONTRACT_NO_ENTRY_INVARIANTS
and BOOST_CONTRACT_NO_EXIT_INVARIANTS),
and BOOST_CONTRACT_NO_CHECKS
(see Disable
Contract Checking).
Alternatively, this library provides a macro-based interface defined in
boost/contract_macro.hpp
that can also be used to completely disable compile-time and run-time overheads
introduced by contracts but without the burden of manually writing the #ifndefBOOST_CONTRACT_NO_... statements. For example, the following
code shows how to use both the boost/contract_macro.hpp
macro interface and the #ifndefBOOST_CONTRACT_NO_...
statements to completely disable compile-time and run-time overheads for
non-member function contracts (see ifdef_macro.cpp
and ifdef.cpp):
Macro Interface
#ifndefBOOST_CONTRACT_NO_... Statements
// Use macro interface to completely disable contract code compilation.#include<boost/contract_macro.hpp>intinc(int&x){intresult;BOOST_CONTRACT_OLD_PTR(int)(old_x,x);BOOST_CONTRACT_FUNCTION()BOOST_CONTRACT_PRECONDITION([&]{BOOST_CONTRACT_ASSERT(x<std::numeric_limits<int>::max());})BOOST_CONTRACT_POSTCONDITION([&]{BOOST_CONTRACT_ASSERT(x==*old_x+1);BOOST_CONTRACT_ASSERT(result==*old_x);});returnresult=x++;}// Use #ifdef to completely disable contract code compilation.#include<boost/contract/core/config.hpp>#ifndefBOOST_CONTRACT_NO_ALL#include<boost/contract.hpp>#endifintinc(int&x){intresult;#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr<int>old_x=BOOST_CONTRACT_OLDOF(x);#endif#ifndefBOOST_CONTRACT_NO_FUNCTIONSboost::contract::checkc=boost::contract::function()#ifndefBOOST_CONTRACT_NO_PRECONDITIONS.precondition([&]{BOOST_CONTRACT_ASSERT(x<std::numeric_limits<int>::max());})#endif#ifndefBOOST_CONTRACT_NO_POSTCONDITIONS.postcondition([&]{BOOST_CONTRACT_ASSERT(x==*old_x+1);BOOST_CONTRACT_ASSERT(result==*old_x);})#endif;#endifreturnresult=x++;}
The same can be done to disable contract code complication for private and
protected functions. The BOOST_CONTRACT_OLD_PTR_IF_COPYABLE
macro is provided to handle non-copyable old value types (similar to boost::contract::old_ptr_if_copyable).
For constructors, destructors, and public functions the boost/contract_macro.hpp
macro interface and the #ifndefBOOST_CONTRACT_NO_...
statements can be used as follow (see ifdef_macro.cpp
and ifdef.cpp):
Macro Interface
#ifndefBOOST_CONTRACT_NO_... Statements
classintegers#defineBASESpublicpushable<int>:// Left in code (almost no overhead).privateboost::contract::constructor_precondition<integers>,BASES{// Followings left in code (almost no overhead).friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_INVARIANT({BOOST_CONTRACT_ASSERT(size()<=capacity());})public:integers(intfrom,intto):BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(integers)([&]{BOOST_CONTRACT_ASSERT(from<=to);}),vect_(to-from+1){BOOST_CONTRACT_CONSTRUCTOR(this)BOOST_CONTRACT_POSTCONDITION([&]{BOOST_CONTRACT_ASSERT(int(size())==(to-from+1));});for(intx=from;x<=to;++x)vect_.at(x-from)=x;}virtual~integers(){BOOST_CONTRACT_DESTRUCTOR(this);// Check invariants.}virtualvoidpush_back(intconst&x,boost::contract::virtual_*v=0// Left in code (almost no overhead).)/* override */{BOOST_CONTRACT_OLD_PTR(unsigned)(old_size);BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_push_back)(v,&integers::push_back,this,x)BOOST_CONTRACT_PRECONDITION([&]{BOOST_CONTRACT_ASSERT(size()<max_size());})BOOST_CONTRACT_OLD([&]{old_size=BOOST_CONTRACT_OLDOF(v,size());})BOOST_CONTRACT_POSTCONDITION([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);})BOOST_CONTRACT_EXCEPT([&]{BOOST_CONTRACT_ASSERT(size()==*old_size);});vect_.push_back(x);}private:BOOST_CONTRACT_OVERRIDE(push_back)// Left in code (almost no overhead)./* ... */classintegers#defineBASESpublicpushable<int>:#ifndefBOOST_CONTRACT_NO_PRECONDITIONSprivateboost::contract::constructor_precondition<integers>,BASES#elseBASES#endif{#ifndefBOOST_CONTRACT_NO_ALLfriendclassboost::contract::access;#endif#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONStypedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#endif#undefBASES#ifndefBOOST_CONTRACT_NO_INVARIANTSvoidinvariant()const{BOOST_CONTRACT_ASSERT(size()<=capacity());}#endifpublic:integers(intfrom,intto):#ifndefBOOST_CONTRACT_NO_PRECONDITIONSboost::contract::constructor_precondition<integers>([&]{BOOST_CONTRACT_ASSERT(from<=to);}),#endifvect_(to-from+1){#ifndefBOOST_CONTRACT_NO_CONSTRUCTORSboost::contract::checkc=boost::contract::constructor(this)#ifndefBOOST_CONTRACT_NO_POSTCONDITIONS.postcondition([&]{BOOST_CONTRACT_ASSERT(int(size())==(to-from+1));})#endif;#endiffor(intx=from;x<=to;++x)vect_.at(x-from)=x;}virtual~integers(){#ifndefBOOST_CONTRACT_NO_DESTRUCTORS// Check invariants.boost::contract::checkc=boost::contract::destructor(this);#endif}virtualvoidpush_back(intconst&x#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONS,boost::contract::virtual_*v=0#endif)/* override */{#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr<unsigned>old_size;#endif#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkc=boost::contract::public_function<override_push_back>(v,&integers::push_back,this,x)#ifndefBOOST_CONTRACT_NO_PRECONDITIONS.precondition([&]{BOOST_CONTRACT_ASSERT(size()<max_size());})#endif#ifndefBOOST_CONTRACT_NO_OLDS.old([&]{old_size=BOOST_CONTRACT_OLDOF(v,size());})#endif#ifndefBOOST_CONTRACT_NO_POSTCONDITIONS.postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);})#endif#ifndefBOOST_CONTRACT_NO_EXCEPTS.except([&]{BOOST_CONTRACT_ASSERT(size()==*old_size);})#endif;#endifvect_.push_back(x);}private:#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSBOOST_CONTRACT_OVERRIDE(push_back)#endif/* ... */
Static and volatile class invariants can be programmed using BOOST_CONTRACT_STATIC_INVARIANT
and BOOST_CONTRACT_INVARIANT_VOLATILE
respectively (these macros expand code equivalent to the staticvoidBOOST_CONTRACT_STATIC_INVARIANT_FUNC() and voidBOOST_CONTRACT_INVARIANT_FUNC()constvolatile
functions).
The boost/contract_macro.hpp
macro interface is usually preferred because more concise and easier to use
than programming #ifndefBOOST_CONTRACT_NO_...
statements by hand. However, C++ macros expand on a single line of code and
that can make compiler errors less useful when using this macro interface
plus all contract assertions within a given set of preconditions, postconditions,
exception guarantees, and class invariants will list the same line number
in error messages when assertions fail at run-time (but error messages still
list the assertion code and that should still allow programmers to identify
the specific assertion that failed). Finally, the macro interface leaves
a bit of contract decorations in the code but that should add no measurable
compile-time or run-time overhead (specifically, extra boost::contract::virtual_* parameters, calls to boost::contract::constructor_precondition
default constructor which does nothing, BOOST_CONTRACT_BASE_TYPEStypedefs, and boost::contract::access
friendships are left in user code even when contracts are disabled unless
#ifndefBOOST_CONTRACT_NO_... statements are used).
Disabling contract as shown in Disable
Contract Checking leaves the overhead of compiling contract code plus
some small run-time overhead due to the initialization of old value pointers
(even if those will be all null and no old value will be actually copied),
the calls to the contract functions used to initialize boost::contract::check
and boost::contract::constructor_precondition
(even if those calls will be internally optimized by this library to essentially
do nothing), etc. For truly performance critical code for which even such
small run-time overhead might not be acceptable, the macro interface (or
the #ifndefBOOST_CONTRACT_NO_... statements) can be used to completely
disable compile-time and run-time overheads of contracts. However, for such
performance critical code even the overhead of checking simple preconditions
might be too much so it might be best to not program contracts at all.
Usually, if the overhead of checking preconditions and other assertions is
already considered acceptable for an application then the compile-time overhead
of contracts should not represent an issue and it should be sufficient to
disable contract checking at run-time as indicated in Disable
Contract Checking (without a real need to use the boost/contract_macro.hpp
macro interface or the #ifndefBOOST_CONTRACT_NO_...
statements in most cases).
Separate
Body Implementation
Contracts are part of the program specifications and not of its implementation
(see Specifications
vs. Implementation). However, this library uses function definitions
to program contracts so contract code appears together with the function
implementation code. This is not ideal (even if contracts programmed using
this library will always appear at the very beginning of the function definition
so programmers will easily be able to distinguish contract code from the
rest of the function implementation code so this might not be real limitation
in practise).
In some cases, it might be desirable to completely separate the contract
code from the function implementation code. For example, this could be necessary
for software that ships only header files and compiled object files to its
users. If contracts are programmed in function definitions that are compiled
in the object files, users will not be able to see the contract code to understand
semantics and usage of the functions (again, this might not be a real problem
in practice for example if contracts are already somehow extracted from the
source code by some tool and presented as part of the documentation of the
shipped software).
In any case, when it is truly important to separate contracts from function
implementation code, function implementations can be programmed in extra
body functions (here named ..._body, but any other naming scheme could
be used) that are compiled in object files. Function definitions that remain
in header files instead will contain just contract code followed by calls
to the extra body functions. This technique allows to keep the contract code
in header files while separating the implementation code to source and object
files. However, this adds the overhead of manually programming an extra function
declaration for each body function (plus the limitation that constructor
member initialization lists must be programmed in header files because that
is where constructors need to be defined to list constructor contract code).
When used as default parameter values, lambda functions allow to program
code statements within function declarations. However, these lambadas cannot
be effectively used to program contracts in function declarations instead
of definitions. That is because the C++11 standard does not allow lambdas
in function declarations to capture any variable (for the good reason that
it is not at all obvious how to correctly define the semantics of such
captures). For example, the following code is not valid C++ and it does
not compile:
// Specifications (in declaration).intinc(int&x,// Error: Lambdas in default parameters cannot capture `this`, `x`, or any other variable.std::function<void()>pre=[&]{BOOST_CONTRACT_ASSERT(x<std::numeric_limits<int>::max());},std::function<void(intconst&,boost::contract::old_ptr<int>const&)>post=[&](intconst&result,boost::contract::old_ptr<int>const&old_x){BOOST_CONTRACT_ASSERT(x==*old_x+1);BOOST_CONTRACT_ASSERT(result==*old_x);});// Implementation (in definition).intinc(int&x,std::function<void()>pre,std::function<void(intconst&,boost::contract::old_ptr<int>const&)>post){intresult;boost::contract::old_ptr<int>old_x=BOOST_CONTRACT_OLDOF(x);boost::contract::checkc=boost::contract::function().precondition(pre).postcondition(std::bind(post,std::cref(result),std::cref(old_x)));returnresult=x++;// Function body.}
In any case, even if the above code compiled, it would require significant
boiler-plate code to bind return and old values.
For example, the following header file only contains function declarations,
contract code, and constructor member initializations, but it does not contain
the code implementing the function bodies (see separate_body.hpp):
classiarray:privateboost::contract::constructor_precondition<iarray>{public:voidinvariant()const{BOOST_CONTRACT_ASSERT(size()<=capacity());}explicitiarray(unsignedmax,unsignedcount=0):boost::contract::constructor_precondition<iarray>([&]{BOOST_CONTRACT_ASSERT(count<=max);}),// Still, member initializations must be here.values_(newint[max]),capacity_(max){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()==max);BOOST_CONTRACT_ASSERT(size()==count);});constructor_body(max,count);// Separate constructor body impl.}virtual~iarray(){boost::contract::checkc=boost::contract::destructor(this);// Inv.destructor_body();// Separate destructor body implementation.}virtualvoidpush_back(intvalue,boost::contract::virtual_*v=0){boost::contract::old_ptr<unsigned>old_size=BOOST_CONTRACT_OLDOF(v,size());boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(size()<capacity());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);});push_back_body(value);// Separate member function body implementation.}private:// Contracts in class declaration (above), but body implementations are not.voidconstructor_body(unsignedmax,unsignedcount);voiddestructor_body();voidpush_back_body(intvalue);/* ... */
Instead, the function bodies are implemented in a separate source file (see
separate_body.cpp):
voidiarray::constructor_body(unsignedmax,unsignedcount){for(unsignedi=0;i<count;++i)values_[i]=int();size_=count;}voidiarray::destructor_body(){delete[]values_;}voidiarray::push_back_body(intvalue){values_[size_++]=value;}/* ... */
The same technique can be used for non-member, private, and protected functions,
etc.
When contracts are programmed only in .cpp files and
also all this library headers are #included
only from .cpp files, then these .cpp
files can be compiled disabling specific contract checking (for example,
BOOST_CONTRACT_NO_POSTCONDITIONS,
BOOST_CONTRACT_NO_EXCEPTS,
and BOOST_CONTRACT_NO_EXIT_INVARIANTS,
see Disable
Contract Checking). Then the code in these .cpp
files will always have such contract checking disabled even when linked
to some other user code that might have been compiled with a different
set of contracts disabled (i.e., a different set of BOOST_CONTRACT_NO_... macros defined). This technique might
be useful to ship compiled object files (e.g., for a library) that will
never check some contracts (e.g., postconditions, exception guarantees,
and exit invariants) regardless of the definition of the BOOST_CONTRACT_NO_...
macros used to compile code that links against the shipped object files.
On the flip side, if contracts are programmed only in header files (e.g.,
using extra ..._body
functions as shown in this section) and this library headers are #included only in these header files
that are being shipped, then end users can enable or disables contract
checking of the shipped code by defining the BOOST_CONTRACT_NO_... macros when they compile the shipped
header files as part of their code. This technique might be useful in other
situations when programmers that ship code want to leave it up the their
end users to decide which contracts of the shipped code should be checked
at run-time.
No
Lambda Functions (No C++11)
This section shows how to use this library without C++11 lambda functions.
This has some advantages:
It allows to use this library on compilers that do not support C++11
lambda functions (essentially most C++03 compilers with adequate support
for SFINAE can be used in that case, see No
Macros to also avoid using variadic macros).
Alternatively, on compilers that do not support C++11 lambda functions,
Boost.LocalFunction
could be used to program the contract functors still within the function
definitions (for example, see no_lambda_local_func.cpp).
In general, such a code is less verbose than the example shown in this
section that uses contract functions programmed outside of the original
function definitions (about 30% less lines of code) but the contract
code is hard to read. Other libraries could also be used to program
the contract functors without C++11 lambda functions (Boost.Lambda,
Boost.Fusion, etc.) but again all these techniques will result in contract
code either more verbose, or harder to read and maintain than the code
that uses C++11 lambda functions.
Contract functions (i.e., the ..._precondition, ..._old, and ..._postcondition functions in the example
below) can be programmed to fully enforce constant-correctness and other
contract requirements at compile-time (see Constant-Correctness).
If C++ allowed lambda functions to capture variables by constant reference
(for example allowing a syntax like this [const&]{...} and [const&variable-name]{...},
see https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/0UKQw9eo3N0)
also lambdas could be used to program contract functors that fully
enforce Constant-Correctness
at compile-time. Note that C++11 lambdas allow to capture variables
by value (using [=]{...}
and [variable-name]{...})
and these value captures are const
(unless the lambda is explicitly declared mutable)
but they are not suitable to program postconditions and exception guarantees
using this library (because those require capturing by reference, see
Postconditions
and Exception
Guarantees), plus they introduce a copy of the captured value
that might be too expensive in general and therefore not suitable for
preconditions either.
Code of the contract functions is separated from function body implementations
(see Separate
Body Implementation).
However, not using C++11 lambda functions comes at the significant cost of
having to manually program the extra contract functions and related boiler-plate
code. For example, the header file (see no_lambdas.hpp):
classiarray:privateboost::contract::constructor_precondition<iarray>{public:staticvoidstatic_invariant(){BOOST_CONTRACT_ASSERT(instances()>=0);}voidinvariant()const{BOOST_CONTRACT_ASSERT(size()<=capacity());}explicitiarray(unsignedmax,unsignedcount=0);staticvoidconstructor_precondition(unsignedconstmax,unsignedconstcount){BOOST_CONTRACT_ASSERT(count<=max);}staticvoidconstructor_old(boost::contract::old_ptr<int>&old_instances){old_instances=BOOST_CONTRACT_OLDOF(instances());}voidconstructor_postcondition(unsignedconstmax,unsignedconstcount,boost::contract::old_ptr<int>constold_instances)const{BOOST_CONTRACT_ASSERT(capacity()==max);BOOST_CONTRACT_ASSERT(size()==count);BOOST_CONTRACT_ASSERT(instances()==*old_instances+1);}virtual~iarray();voiddestructor_old(boost::contract::old_ptr<int>&old_instances)const{old_instances=BOOST_CONTRACT_OLDOF(instances());}staticvoiddestructor_postcondition(boost::contract::old_ptr<int>constold_instances){BOOST_CONTRACT_ASSERT(instances()==*old_instances-1);}virtualvoidpush_back(intvalue,boost::contract::virtual_*v=0);voidpush_back_precondition()const{BOOST_CONTRACT_ASSERT(size()<capacity());}voidpush_back_old(boost::contract::virtual_*v,boost::contract::old_ptr<unsigned>&old_size)const{old_size=BOOST_CONTRACT_OLDOF(v,size());}voidpush_back_postcondition(boost::contract::old_ptr<unsigned>constold_size)const{BOOST_CONTRACT_ASSERT(size()==*old_size+1);}unsignedcapacity()const;unsignedsize()const;staticintinstances();private:int*values_;unsignedcapacity_;unsignedsize_;staticintinstances_;};
And, the source file (see no_lambdas.cpp):
iarray::iarray(unsignedmax,unsignedcount):boost::contract::constructor_precondition<iarray>(boost::bind(&iarray::constructor_precondition,max,count)),values_(newint[max]),// Member initializations can be here.capacity_(max){boost::contract::old_ptr<int>old_instances;boost::contract::checkc=boost::contract::constructor(this).old(boost::bind(&iarray::constructor_old,boost::ref(old_instances))).postcondition(boost::bind(&iarray::constructor_postcondition,this,boost::cref(max),boost::cref(count),boost::cref(old_instances)));for(unsignedi=0;i<count;++i)values_[i]=int();size_=count;++instances_;}iarray::~iarray(){boost::contract::old_ptr<int>old_instances;boost::contract::checkc=boost::contract::destructor(this).old(boost::bind(&iarray::destructor_old,this,boost::ref(old_instances))).postcondition(boost::bind(&iarray::destructor_postcondition,boost::cref(old_instances)));delete[]values_;--instances_;}voidiarray::push_back(intvalue,boost::contract::virtual_*v){boost::contract::old_ptr<unsigned>old_size;boost::contract::checkc=boost::contract::public_function(v,this).precondition(boost::bind(&iarray::push_back_precondition,this)).old(boost::bind(&iarray::push_back_old,this,boost::cref(v),boost::ref(old_size))).postcondition(boost::bind(&iarray::push_back_postcondition,this,boost::cref(old_size)));values_[size_++]=value;}unsignediarray::capacity()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returncapacity_;}unsignediarray::size()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnsize_;}intiarray::instances(){// Check static invariants.boost::contract::checkc=boost::contract::public_function<iarray>();returninstances_;}intiarray::instances_=0;
If programmers also want to fully enforce all contract programming constant-correctness
requirements at compile-time, they should follow these rules when programming
the contract functions (see Constant-Correctness):
Precondition functions (i.e., the ..._precondition functions in the example
above) can take their arguments either by const
value or by const&,
and when they are member functions they should be either static or const
functions.
Postcondition functions (i.e., the ..._postcondition functions in the example
above) should take their arguments by const&, and when they are member functions
they should be either static
or const functions.
Similarly, exception guarantee functions (not shown in the example above)
should take their arguments by const&, and when they are member functions
they should be either static
or const functions.
Old value functions (i.e., the ..._old functions in the example above)
should take their arguments by const& a part from old value pointers that
should be taken by &
(so only old value pointers can be modified), and when they are member
functions they should be either static
or const functions.
For constructors: Precondition, old value, and exception guarantee functions
should be static (because
there is no valid object this
if the constructor body does not run successfully, see Constructor
Calls).
For destructors: Postcondition functions should be static
(because there is no valid object this
after the destructor body runs successfully, but exception guarantee
functions do not have to be static
since the object this is
still valid because the destructor body did not run successfully, see
Destructor
Calls).
Note that the extra contract functions also allow to keep the contract code
in the header file while all function bodies are implemented in a separate
source file (including the constructor member initialization list, that could
not be done with the techniques shown in Separate
Body Implementation).
In this example, bind was
used to generate nullary functors from the contract functions. As always
with bind, cref and ref
must be used to bind arguments by const& and &
respectively, plus it might be necessary to explicitly static_cast
the function pointer passed to bind
for overloaded functions.
Also note that the contract functions can always be declared
private if programmers need
to exactly control the public members of the class (this was not done in
this example only for brevity).
The authors think this library is most useful when used together with C++11
lambda functions (because of the large amount of boiler-plate code required
when C++11 lambdas are not used as also shown by the example above).
No
Macros (and No Variadic Macros)
It is possible to specify contracts without using most of the macros provided
by this library and programming the related code manually instead (the only
macros that cannot be programmed manually are BOOST_CONTRACT_OVERRIDE,
BOOST_CONTRACT_OVERRIDES,
and BOOST_CONTRACT_NAMED_OVERRIDE).
Some of this library macros are variadic macros, others are not (see below).
Variadic macros were officially added to the language in C++11 but most
compilers have been supporting them as an extension for a long time, plus
all compilers that support C++11 lambda functions should also support C++11
variadic macros (and this library might rarely be used without the convenience
of C++11 lambda functions, see No
Lambda Functions).
Compilation times of this library were measured to be comparable between
compilers that support variadic macros and compilers that do not.
Therefore, the rest of this section can be considered mainly
a curiosity because programmers should seldom, if ever, need to use this
library without using its macros.
Overrides
As shown in Public
Function Overrides and Named
Overrides, this library provides the BOOST_CONTRACT_OVERRIDE
and BOOST_CONTRACT_NAMED_OVERRIDE
macros to program contracts for overriding public functions (see BOOST_CONTRACT_MAX_ARGS for compilers
that do not support variadic templates). Rationale: The BOOST_CONTRACT_MAX_ARGS
macro is named after BOOST_FUNCTION_MAX_ARGS.
These macro cannot be programmed manually but they are not variadic
macros (so programmers should be able to use them on any C++ compiler with
a sound support for SFINAE). Rationale: These macros expand to SFINAE-based
introspection template code that are too complex to be programmed manually
by users (that remains the case even if C++14 generic lambdas were to be
used here). On a related note, in theory using C++14 generic lambdas, the
BOOST_CONTRACT_OVERRIDE
macro could be re-implemented in a way that can be expanded at function
scope, instead of class scope (but there is not really a need to do that).
The BOOST_CONTRACT_OVERRIDES
macro is a variadic macro instead but programmes can manually repeat the
non-variadic macro BOOST_CONTRACT_OVERRIDE
for each overriding public function name on compilers that do not support
variadic macros.
Assertions
(Not Variadic)
As shown in Preconditions,
Postconditions,
Exception Guarantees,
Class Invariants,
etc. this library provides the BOOST_CONTRACT_ASSERT
macro to assert contract conditions. This is not a variadic macro and programmers
should be able to use it on all C++ compilers. In any case, the invocation
BOOST_CONTRACT_ASSERT(cond) simply expands to code equivalent to the
following: Rationale: There is no need for the code
expanded by BOOST_CONTRACT_ASSERT
to also use C++11 __func__.
That is because __func__
will always expand to the name operator() of the functor used to program the contract
assertions (e.g., the internal name the compiler assigns to lambda functions)
and it will not expand to the name of the actual function enclosing the
contract declaration.
if(!(cond)){throwboost::contract::assertion_failure(__FILE__,__LINE__,BOOST_PP_STRINGIZE(cond));}
In fact, this library considers any exception thrown from within preconditions,
postconditions, exception guarantees, and class invariants as a contract
failure and reports it calling the related contract failure handler (boost::contract::precondition_failure,
etc.). If there is a need for it, programmers can always program contract
assertions that throw specific user-defined exceptions as follow (see Throw
on Failures):
if(!cond)throwexception-object;
However, using BOOST_CONTRACT_ASSERT
is convenient because it always allows this library to show an informative
message in case of assertion failure containing the assertion code, file
name, line number, etc.
As shown in Assertion
Levels, this library pre-defines BOOST_CONTRACT_ASSERT_AUDIT
and BOOST_CONTRACT_ASSERT_AXIOM
assertion levels. These macros are not variadic macros and programmers should
be able to use them on all C++ compilers. In any case, their implementations
are equivalent to the following:
#ifdefBOOST_CONTRACT_AUDITS#defineBOOST_CONTRACT_ASSERT_AUDIT(cond)\BOOST_CONTRACT_ASSERT(cond)#else#defineBOOST_CONTRACT_ASSERT_AUDIT(cond)\BOOST_CONTRACT_ASSERT(true||(cond))#endif#defineBOOST_CONTRACT_ASSERT_AXIOM(cond)\BOOST_CONTRACT_ASSERT(true||(cond))Base
Types (Variadic)
As shown in Base
Classes, this library provides the BOOST_CONTRACT_BASE_TYPES
variadic macro to declare the base_types
member type that will expand to the list of all public bases for a derived
class. Programmers can also declare base_types
without using BOOST_CONTRACT_BASE_TYPES
at the cost of writing a bit more code and increase maintenance efforts.
For example (see base_types_no_macro.cpp):
#include<boost/mpl/vector.hpp>classchars:privateboost::contract::constructor_precondition<chars>,publicunique_chars,publicvirtualpushable<char>,virtualprotectedhas_size,privatehas_empty{public:// Program `base_types` without macros (list only public bases).typedefboost::mpl::vector<unique_chars,pushable<char>>base_types;/* ... */
The base_types member type
must be a boost::mpl::vector
which must list all and onlypublic
base classes (because only public bases subcontract, see Function
Calls), and in the same order these public base classes appear in
the derived class inheritance list. If the BOOST_CONTRACT_BASE_TYPES
macro is not used, it is the responsibility of the programmers to maintain
the correct list of bases in the boost::mpl::vector each time the derived class inheritance
list changes (this might significantly complicate maintenance).
In general, it is recommended to use the BOOST_CONTRACT_BASE_TYPES
macro whenever possible.
Old
Values (Variadic)
As shown in Old Values,
this library provides the BOOST_CONTRACT_OLDOF
variadic macro to assign old value copies. Programmers can also assign old
values without using BOOST_CONTRACT_OLDOF
at the cost of writing a bit more code manually. For example (see old_no_macro.cpp):
template<typenameT>classvector{public:virtualvoidpush_back(Tconst&value,boost::contract::virtual_*v=0){// Program old value instead of using `OLD(size())` macro.boost::contract::old_ptr<unsigned>old_size=boost::contract::make_old(v,boost::contract::copy_old(v)?size():boost::contract::null_old());boost::contract::checkc=boost::contract::public_function(v,this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);});vect_.push_back(value);}/* ... */
The ternary operator boost::contract::copy_old(v)?size():boost::contract::null_old() must be used here to avoid evaluating and
copying the old value expression size() when boost::contract::copy_old
returns false (because old values
are not being copied when postcondition and exception guarantee checking
is disabled at run-time, an overridden virtual function call is not checking
postconditions or exception guarantees yet, etc.). The enclosing boost::contract::make_old
copies the old value expression and creates an old value pointer. Otherwise,
boost::contract::null_old
indicates that a null old value pointer should be created.
The boost::contract::make_old
and boost::contract::copy_old
functions are used exactly as shown above but without the extra v parameter when they are called from within
non-virtual functions (see Public
Function Overrides). The old value pointer returned by boost::contract::make_old
can be assigned to either boost::contract::old_ptr
or boost::contract::old_ptr_if_copyable
(see Old
Value Requirements).
In general, it is recommended to use the BOOST_CONTRACT_OLDOF
macro whenever possible.
Macro
Interface (Variadic)
Almost all macros defined in boost/contract_macro.hpp
are variadic macros. On compilers that do not support variadic macros, programmers
can manually disable contract code compilation using #ifndefBOOST_CONTRACT_NO_...
statements as shown in Disable
Contract Compilation.
Examples
This section lists some examples taken from different sources discussing contract
programming and implemented here using this library.
Some of these examples might be from old code, containing obsolete coding
practices, not optimized for execution speed, not complete, and they might
be more relevant in the context of programming languages different from C++.
Nevertheless, programmers are encouraged to review these examples to see
a few diverse uses of this library that might be relevant to their needs.
The examples in this sections are taken from the following sources:
[N1962]: Examples from a detailed and
complete proposal to add contract programming to C++11 (unfortunately,
this proposal was never accepted into the standard).
[Meyer97]: Examples from the Eiffel
programming language (reprogrammed here in C++ using this library).
[Mitchell02]: Additional examples
from the Eiffel programming language (reprogrammed here in C++ using this
library).
[Cline90]: Examples from a very early
proposal called Annotated C++ (A++) to add contract programming to C++
(A++ was never implemented or proposed for addition to the standard).
The following are some examples of particular interest:
[N1962] Vector: Complete set
of contracts for std::vector, plus a comparison with [N1962] syntax.
[N1962] Square Root: Comparison
with D syntax.
[Mitchell02] Counter:
Subcontracting.
[Meyer97] Stack4: Comparison
with Eiffel syntax.
[Cline90] Vector: Comparison
with A++ syntax.
Most of the examples listed here use old values and class invariants which
are instead not supported by [P0380]. Therefore,
there is not meaningful example here that can be directly implemented and compared
using [P0380] syntax.
[N1962] Vector: Contracts for STL
vector and comparison with [N1962] proposed
syntax
On compilers that support C++17 ifconstexpr, the following example using
this library can be simplified removing boost::contract::condition_if
and related functor templates such as all_of_equal_to,
etc., making it more similar to the pseudo-code on the right-hand side (see
Assertion
Requirements).
This library
[N1962] proposal (not accepted in C++) plus C++17 if constexpr#include<boost/contract.hpp>#include<boost/bind.hpp>#include<boost/optional.hpp>#include<boost/algorithm/cxx11/all_of.hpp>#include<boost/type_traits/has_equal_to.hpp>#include<boost/next_prior.hpp>#include<vector>#include<functional>#include<iterator>#include<memory>#include<cassert>// Could be programmed at call site with C++14 generic lambdas.structall_of_equal_to{typedefboolresult_type;template<typenameInputIter,typenameT>result_typeoperator()(InputIterfirst,InputIterlast,Tconst&value){returnboost::algorithm::all_of_equal(first,last,value);}template<typenameInputIter>result_typeoperator()(InputIterfirst,InputIterlast,InputIterwhere){for(InputIteri=first,j=where;i!=last;++i,++j){if(*i!=*j)returnfalse;}returntrue;}};template<typenameIter>boolvalid(Iterfirst,Iterlast);// Cannot implement in C++ (for axiom only).template<typenameIter>boolcontained(Iterfirst1,Iterlast1,Iterfirst2,Iterlast2);// For axiom.// STL vector requires T copyable but not equality comparable.template<typenameT,classAllocator=std::allocator<T>>classvector{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(empty()==(size()==0));BOOST_CONTRACT_ASSERT(std::distance(begin(),end())==int(size()));BOOST_CONTRACT_ASSERT(std::distance(rbegin(),rend())==int(size()));BOOST_CONTRACT_ASSERT(size()<=capacity());BOOST_CONTRACT_ASSERT(capacity()<=max_size());}public:typedeftypenamestd::vector<T,Allocator>::allocator_typeallocator_type;typedeftypenamestd::vector<T,Allocator>::pointerpointer;typedeftypenamestd::vector<T,Allocator>::const_pointerconst_pointer;typedeftypenamestd::vector<T,Allocator>::referencereference;typedeftypenamestd::vector<T,Allocator>::const_referenceconst_reference;typedeftypenamestd::vector<T,Allocator>::value_typevalue_type;typedeftypenamestd::vector<T,Allocator>::iteratoriterator;typedeftypenamestd::vector<T,Allocator>::const_iteratorconst_iterator;typedeftypenamestd::vector<T,Allocator>::size_typesize_type;typedeftypenamestd::vector<T,Allocator>::difference_typedifference_type;typedeftypenamestd::vector<T,Allocator>::reverse_iteratorreverse_iterator;typedeftypenamestd::vector<T,Allocator>::const_reverse_iteratorconst_reverse_iterator;vector():vect_(){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(empty());});}explicitvector(Allocatorconst&alloc):vect_(alloc){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(empty());BOOST_CONTRACT_ASSERT(get_allocator()==alloc);});}explicitvector(size_typecount):vect_(count){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),begin(),end(),T())));});}vector(size_typecount,Tconst&value):vect_(count,value){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),begin(),end(),boost::cref(value))));});}vector(size_typecount,Tconst&value,Allocatorconst&alloc):vect_(count,value,alloc){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),begin(),end(),boost::cref(value))));BOOST_CONTRACT_ASSERT(get_allocator()==alloc);});}template<typenameInputIter>vector(InputIterfirst,InputIterlast):vect_(first,last){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(std::distance(first,last)==int(size()));});}template<typenameInputIter>vector(InputIterfirst,InputIterlast,Allocatorconst&alloc):vect_(first,last,alloc){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(std::distance(first,last)==int(size()));BOOST_CONTRACT_ASSERT(get_allocator()==alloc);});}/* implicit */vector(vectorconst&other):vect_(other.vect_){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<vector<T>>(),boost::cref(*this),boost::cref(other))));});}vector&operator=(vectorconst&other){boost::optional<vector&>result;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<vector<T>>(),boost::cref(*this),boost::cref(other))));BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<vector<T>>(),boost::cref(*result),boost::cref(*this))));});if(this!=&other)vect_=other.vect_;return*(result=*this);}virtual~vector(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}voidreserve(size_typecount){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count<max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()>=count);});vect_.reserve(count);}size_typecapacity()const{size_typeresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result>=size());});returnresult=vect_.capacity();}iteratorbegin(){iteratorresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{if(empty())BOOST_CONTRACT_ASSERT(result==end());});returnresult=vect_.begin();}const_iteratorbegin()const{const_iteratorresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{if(empty())BOOST_CONTRACT_ASSERT(result==end());});returnresult=vect_.begin();}iteratorend(){// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnvect_.end();}const_iteratorend()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnvect_.end();}reverse_iteratorrbegin(){iteratorresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{if(empty())BOOST_CONTRACT_ASSERT(result==rend());});returnresult=vect_.rbegin();}const_reverse_iteratorrbegin()const{const_reverse_iteratorresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{if(empty())BOOST_CONTRACT_ASSERT(result==rend());});returnresult=vect_.rbegin();}reverse_iteratorrend(){// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnvect_.rend();}const_reverse_iteratorrend()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnvect_.rend();}voidresize(size_typecount,Tconst&value=T()){boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);if(count>*old_size){BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),begin()+*old_size,end(),boost::cref(value))));}});vect_.resize(count,value);}size_typesize()const{size_typeresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result<=capacity());});returnresult=vect_.size();}size_typemax_size()const{size_typeresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result>=capacity());});returnresult=vect_.max_size();}boolempty()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result==(size()==0));});returnresult=vect_.empty();}Allocatorget_allocator()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnvect_.get_allocator();}referenceat(size_typeindex){// Check invariants, no pre (throw out_of_range for invalid index).boost::contract::checkc=boost::contract::public_function(this);returnvect_.at(index);}const_referenceat(size_typeindex)const{// Check invariants, no pre (throw out_of_range for invalid index).boost::contract::checkc=boost::contract::public_function(this);returnvect_.at(index);}referenceoperator[](size_typeindex){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(index<size());});returnvect_[index];}const_referenceoperator[](size_typeindex)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(index<size());});returnvect_[index];}referencefront(){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());});returnvect_.front();}const_referencefront()const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());});returnvect_.front();}referenceback(){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());});returnvect_.back();}const_referenceback()const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());});returnvect_.back();}voidpush_back(Tconst&value){boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::old_ptr<size_type>old_capacity=BOOST_CONTRACT_OLDOF(capacity());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(size()<max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);BOOST_CONTRACT_ASSERT(capacity()>=*old_capacity);BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<T>(),boost::cref(back()),boost::cref(value))));});vect_.push_back(value);}voidpop_back(){boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size-1);});vect_.pop_back();}template<typenameInputIter>voidassign(InputIterfirst,InputIterlast){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT_AXIOM(!contained(begin(),end(),first,last));}).postcondition([&]{BOOST_CONTRACT_ASSERT(std::distance(first,last)==int(size()));});vect_.assign(first,last);}voidassign(size_typecount,Tconst&value){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count<=max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),begin(),end(),boost::cref(value))));});vect_.assign(count,value);}iteratorinsert(iteratorwhere,Tconst&value){iteratorresult;boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::old_ptr<size_type>old_capacity=BOOST_CONTRACT_OLDOF(capacity());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(size()<max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+1);BOOST_CONTRACT_ASSERT(capacity()>=*old_capacity);BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(std::equal_to<T>(),boost::cref(*result),boost::cref(value))));if(capacity()>*old_capacity){BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(),end()));}else{BOOST_CONTRACT_ASSERT_AXIOM(!valid(where,end()));}});returnresult=vect_.insert(where,value);}voidinsert(iteratorwhere,size_typecount,Tconst&value){boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::old_ptr<size_type>old_capacity=BOOST_CONTRACT_OLDOF(capacity());boost::contract::old_ptr<iterator>old_where=BOOST_CONTRACT_OLDOF(where);boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(size()+count<max_size());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size+count);BOOST_CONTRACT_ASSERT(capacity()>=*old_capacity);if(capacity()==*old_capacity){BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),boost::prior(*old_where),boost::prior(*old_where)+count,boost::cref(value))));BOOST_CONTRACT_ASSERT_AXIOM(!valid(where,end()));}elseBOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(),end()));});vect_.insert(where,count,value);}template<typenameInputIter>voidinsert(iteratorwhere,InputIterfirst,InputIterlast){boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::old_ptr<size_type>old_capacity=BOOST_CONTRACT_OLDOF(capacity());boost::contract::old_ptr<iterator>old_where=BOOST_CONTRACT_OLDOF(where);boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(size()+std::distance(first,last)<max_size());BOOST_CONTRACT_ASSERT_AXIOM(!contained(first,last,begin(),end()));}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size()+std::distance(first,last));BOOST_CONTRACT_ASSERT(capacity()>=*old_capacity);if(capacity()==*old_capacity){BOOST_CONTRACT_ASSERT(boost::contract::condition_if<boost::has_equal_to<T>>(boost::bind(all_of_equal_to(),first,last,*old_where)));BOOST_CONTRACT_ASSERT_AXIOM(!valid(where,end()));}elseBOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(),end()));});vect_.insert(where,first,last);}iteratorerase(iteratorwhere){iteratorresult;boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());BOOST_CONTRACT_ASSERT(where!=end());}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size-1);if(empty())BOOST_CONTRACT_ASSERT(result==end());BOOST_CONTRACT_ASSERT_AXIOM(!valid(where,end()));});returnresult=vect_.erase(where);}iteratorerase(iteratorfirst,iteratorlast){iteratorresult;boost::contract::old_ptr<size_type>old_size=BOOST_CONTRACT_OLDOF(size());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(size()>=std::distance(first,last));}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==*old_size-std::distance(first,last));if(empty())BOOST_CONTRACT_ASSERT(result==end());BOOST_CONTRACT_ASSERT_AXIOM(!valid(first,last));});returnresult=vect_.erase(first,last);}voidclear(){boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(empty());});vect_.clear();}voidswap(vector&other){boost::contract::old_ptr<vector>old_me,old_other;#ifdefBOOST_CONTRACT_AUDITSold_me=BOOST_CONTRACT_OLDOF(*this);old_other=BOOST_CONTRACT_OLDOF(other);#endifboost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(get_allocator()==other.get_allocator());}).postcondition([&]{BOOST_CONTRACT_ASSERT_AUDIT(boost::contract::condition_if<boost::has_equal_to<vector<T>>>(boost::bind(std::equal_to<vector<T>>(),boost::cref(*this),boost::cref(*old_other))));BOOST_CONTRACT_ASSERT_AUDIT(boost::contract::condition_if<boost::has_equal_to<vector<T>>>(boost::bind(std::equal_to<vector<T>>(),boost::cref(other),boost::cref(*old_me))));});vect_.swap(other);}friendbooloperator==(vectorconst&left,vectorconst&right){// Check class invariants for left and right objects.boost::contract::checkleft_inv=boost::contract::public_function(&left);boost::contract::checkright_inv=boost::contract::public_function(&right);returnleft.vect_==right.vect_;}private:std::vector<T,Allocator>vect_;};intmain(){// char type has operator==.vector<char>v(3);assert(v.size()==3);assert(boost::algorithm::all_of_equal(v,'\0'));vector<char>const&cv=v;assert(cv==v);vector<char>w(v);assert(w==v);typenamevector<char>::iteratori=v.begin();assert(*i=='\0');typenamevector<char>::const_iteratorci=cv.begin();assert(*ci=='\0');v.insert(i,2,'a');assert(v[0]=='a');assert(v[1]=='a');v.push_back('b');assert(v.back()=='b');structx{};// x type doest not have operator==.vector<x>y(3);assert(y.size()==3);vector<x>const&cy=y;vector<x>z(y);typenamevector<x>::iteratorj=y.begin();assert(j!=y.end());typenamevector<x>::const_iteratorcj=cy.begin();assert(cj!=cy.end());y.insert(j,2,x());y.push_back(x());return0;}// Extra spaces, newlines, etc. for visual alignment with this library code.#include<boost/algorithm/cxx11/all_of.hpp>#include<boost/type_traits/has_equal_to.hpp>#include<boost/next_prior.hpp>#include<vector>#include<iterator>#include<memory>template<classT,classAllocator=std::allocator<T>>classvector{invariant{empty()==(size()==0);std::distance(begin(),end())==int(size());std::distance(rbegin(),rend())==int(size());size()<=capacity();capacity()<=max_size();}public:typedeftypenamestd::vector<T,Allocator>::allocator_typeallocator_type;typedeftypenamestd::vector<T,Allocator>::pointerpointer;typedeftypenamestd::vector<T,Allocator>::const_pointerconst_pointer;typedeftypenamestd::vector<T,Allocator>::referencereference;typedeftypenamestd::vector<T,Allocator>::const_referenceconst_reference;typedeftypenamestd::vector<T,Allocator>::value_typevalue_type;typedeftypenamestd::vector<T,Allocator>::iteratoriterator;typedeftypenamestd::vector<T,Allocator>::const_iteratorconst_iterator;typedeftypenamestd::vector<T,Allocator>::size_typesize_type;typedeftypenamestd::vector<T,Allocator>::difference_typedifference_type;typedeftypenamestd::vector<T,Allocator>::reverse_iteratorreverse_iterator;typedeftypenamestd::vector<T,Allocator>::const_reverse_iteratorconst_reverse_iterator;vector()postcondition{empty();}:vect_(){}explicitvector(Allocatorconst&alloc)postcondition{empty();get_allocator()==alloc;}:vect_(alloc){}explicitvector(size_typecount)postcondition{size()==count;ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(begin(),end(),T());}}:vect_(count){}vector(size_typecount,Tconst&value)postcondition{size()==count;ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(begin(),end(),value);}}:vect_(count,value){}vector(size_typecount,Tconst&value,Allocatorconst&alloc)postcondition{size()==count;ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(begin(),end(),value);}get_allocator()==alloc;}:vect_(count,value,alloc){}template<typenameInputIter>vector(InputIterfirst,InputIterlast)postcondition{std::distance(first,last)==int(size());}:vect_(first,last){}template<typenameInputIter>vector(InputIterfirst,InputIterlast,Allocatorconst&alloc)postcondition{std::distance(first,last)==int(size());get_allocator()==alloc;}:vect_(first,last,alloc){}/* implicit */vector(vectorconst&other)postcondition{ifconstexpr(boost::has_equal_to<T>::value){*this==other;}}:vect_(other.vect_){}vector&operator=(vectorconst&other)postcondition(result){ifconstexpr(boost::has_equal_to<T>::value){*this==other;result==*this;}}{if(this!=&other)vect_=other.vect_;return*this;}virtual~vector(){}voidreserve(size_typecount)precondition{count<max_size();}postcondition{capacity()>=count;}{vect_.reserve(count);}size_typecapacity()constpostcondition(result){result>=size();}{returnvect_.capacity();}iteratorbegin()postcondition{if(empty())result==end();}{returnvect_.begin();}const_iteratorbegin()constpostcondition(result){if(empty())result==end();}{returnvect_.begin();}iteratorend(){returnvect_.end();}const_iteratorend()const{returnvect_.end();}reverse_iteratorrbegin()postcondition(result){if(empty())result==rend();}{returnvect_.rbegin();}const_reverse_iteratorrbegin()constpostcondition(result){if(empty())result==rend();}{returnvect_.rbegin();}reverse_iteratorrend(){returnvect_.rend();}const_reverse_iteratorrend()const{returnvect_.rend();}voidresize(size_typecount,Tconst&value=T())postcondition{size()==count;ifconstexpr(boost::has_equal_to<T>::value){if(count>oldof(size())){boost::algorithm::all_of_equal(begin()+oldof(size()),end(),value);}}}{vect_.resize(count,value);}size_typesize()constpostcondition(result){result<=capacity();}{returnvect_.size();}size_typemax_size()constpostcondition(result){result>=capacity();}{returnvect_.max_size();}boolempty()constpostcondition(result){result==(size()==0);}{returnvect_.empty();}Alloctorget_allocator()const{returnvect_.get_allocator();}referenceat(size_typeindex){// No precondition (throw out_of_range for invalid index).returnvect_.at(index);}const_referenceat(size_typeindex)const{// No precondition (throw out_of_range for invalid index).returnvect_.at(index);}referenceoperator[](size_typeindex)precondition{index<size();}{returnvect_[index];}const_referenceoperator[](size_typeindex)constprecondition{index<size();}{returnvect_[index];}referencefront()precondition{!empty();}{returnvect_.front();}const_referencefront()constprecondition{!empty();}{returnvect_.front();}referenceback()precondition{!empty();}{returnvect_.back();}const_referenceback()constprecondition{!empty();}{returnvect_.back();}voidpush_back(Tconst&value)precondition{size()<max_size();}postcondition{size()==oldof(size())+1;capacity()>=oldof(capacity())ifconstexpr(boost::has_equal_to<T>::value){back()==value;}}{vect_.push_back(value);}voidpop_back()precondition{!empty();}postcondition{size()==oldof(size())-1;}{vect_.pop_back();}template<typenameInputIter>voidassign(InputIterfirst,InputIterlast)// Precondition: [begin(), end()) does not contain [first, last).postcondition{std::distance(first,last)==int(size());}{vect_.assign(first,last);}voidassign(size_typecount,Tconst&vallue)precondition{count<=max_size();}postcondition{ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(begin(),end(),value);}}{vect_.assign(count,value);}iteratorinsert(iteratorwhere,Tconst&value)precondition{size()<max_size();}postcondition(result){size()==oldof(size())+1;capacity()>=oldof(capacity());ifconstexpr(boost::has_equal_to<T>::value){*result==value;}// if(capacity() > oldof(capacity()))// [begin(), end()) is invalid// else// [where, end()) is invalid}{returnvect_.insert(where,value);}voidinsert(iteratorwhere,size_typecount,Tconst&value)precondition{size()+count<max_size();}postcondition{size()==oldof(size())+count;capacity()>=oldof(capacity());if(capacity()==oldof(capacity())){ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(boost::prior(oldof(where)),boost::prior(oldof(where))+count,value);}// [where, end()) is invalid}// else [begin(), end()) is invalid}{vect_.insert(where,count,value);}template<typenameInputIter>voidinsert(iteratorwhere,Iteratorfirst,Iteratorlast)precondition{size()+std::distance(first,last)<max_size();// [first, last) is not contained in [begin(), end())}postcondition{size()==oldof(size())+std::distance(first,last);capacity()>=oldof(capacity());if(capacity()==oldof(capacity())){ifconstexpr(boost::has_equal_to<T>::value){boost::algorithm::all_of_equal(first,last,oldof(where));}// [where, end()) is invalid}// else [begin(), end()) is invalid}{vect_.insert(where,first,last);}iteratorerase(iteratorwhere)precondition{!empty();where!=end();}postcondition(result){size()==oldodsize()-1;if(empty())result==end();// [where, end()) is invalid}{returnvect_.erase(where);}iteratorerase(iteratorfirst,iteratorlast)precondition{size()>=std::distance(first,lasst);}postcondition(result){size()==oldof(size())-std::distance(first,last);if(empty())result==end();// [first, last) is invalid}{returnvect_.erase(first,last);}voidclear()postcondition{empty();}{vect_.clear();}voidswap(vector&other)precondition{get_allocator()==other.get_allocator();}postcondition{ifconstexpr(boost::has_equal_to<T>::value){*this==oldof(other);other==oldof(*this);}}{vect_.swap(other);}friendbooloperator==(vectorconst&left,vectorconst&right){// Cannot check class invariants for left and right objects.returnleft.vect_==right.vect_;}private:std::vector<T,Allocator>vect_;};// End.[N1962]
Circle: Subcontracting#include<boost/contract.hpp>#include<cassert>classshape{public:virtual~shape(){}virtualunsignedcompute_area(boost::contract::virtual_*v=0)const=0;};unsignedshape::compute_area(boost::contract::virtual_*v)const{unsignedresult;boost::contract::checkc=boost::contract::public_function(v,result,this).postcondition([&](intconst&result){BOOST_CONTRACT_ASSERT(result>0);});assert(false);returnresult;}classcircle#defineBASESpublicshape:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_OVERRIDE(compute_area);public:staticintconstpi=3;// Truncated to int from 3.14...explicitcircle(unsigneda_radius):radius_(a_radius){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(radius()==a_radius);});}virtualunsignedcompute_area(boost::contract::virtual_*v=0)const/* override */{unsignedresult;boost::contract::checkc=boost::contract::public_function<override_compute_area>(v,result,&circle::compute_area,this).postcondition([&](unsignedconst&result){BOOST_CONTRACT_ASSERT(result==pi*radius()*radius());});returnresult=pi*radius()*radius();}unsignedradius()const{boost::contract::checkc=boost::contract::public_function(this);returnradius_;}private:unsignedradius_;};intmain(){circlec(2);assert(c.radius()==2);assert(c.compute_area()==12);return0;}[N1962]
Factorial: Recursion#include<boost/contract.hpp>#include<cassert>intfactorial(intn){intresult;boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(n>=0);// Non-negative natural number.BOOST_CONTRACT_ASSERT(n<=12);// Max function input.}).postcondition([&]{BOOST_CONTRACT_ASSERT(result>=1);if(n<2){// Select assertion.BOOST_CONTRACT_ASSERT(result==1);}else{// Assertions automatically disabled in other assertions.// Therefore, this postcondition can recursively call the// function without causing infinite recursion.BOOST_CONTRACT_ASSERT_AUDIT(n*factorial(n-1));}});returnn<2?(result=1):(result=n*factorial(n-1));}intmain(){assert(factorial(4)==24);return0;}[N1962]
Equal: Operators#include<boost/contract.hpp>#include<cassert>// Forward declaration because == and != contracts use one another's function.template<typenameT>booloperator==(Tconst&left,Tconst&right);template<typenameT>booloperator!=(Tconst&left,Tconst&right){boolresult;boost::contract::checkc=boost::contract::function().postcondition([&]{BOOST_CONTRACT_ASSERT(result==!(left==right));});returnresult=(left.value!=right.value);}template<typenameT>booloperator==(Tconst&left,Tconst&right){boolresult;boost::contract::checkc=boost::contract::function().postcondition([&]{BOOST_CONTRACT_ASSERT(result==!(left!=right));});returnresult=(left.value==right.value);}structnumber{intvalue;};intmain(){numbern;n.value=123;assert((n==n)==true);// Explicitly call operator==.assert((n!=n)==false);// Explicitly call operator!=.return0;}[N1962]
Sum: Array parameter#include<boost/contract.hpp>#include<cassert>intsum(intcount,int*array){intresult;boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(count%4==0);});result=0;for(inti=0;i<count;++i)result+=array[i];returnresult;}intmain(){inta[4]={1,2,3,4};assert(sum(4,a)==10);return0;}[N1962]
Square Root: Default parameters and comparison with D syntax
This Library
The D Programming Language
#include<boost/contract.hpp>#include<cmath>#include<cassert>longlsqrt(longx){longresult;boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(x>=0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(result*result<=x);BOOST_CONTRACT_ASSERT((result+1)*(result+1)>x);});returnresult=long(std::sqrt(double(x)));}intmain(){assert(lsqrt(4)==2);return0;}// Extra spaces, newlines, etc. for visual alignment with this library code.longlsqrt(longx)in{assert(x>=0);}out(result){assert(result*result<=x);assert((result+1)*(result+1)>x);}do{returncast(long)std.math.sqrt(cast(real)x);}// End.[Meyer97]
Stack4: Comparison with Eiffel syntax
This Library
The Eiffel Programming Language
// File: stack4.hpp#ifndefSTACK4_HPP_#defineSTACK4_HPP_#include<boost/contract.hpp>// Dispenser with LIFO access policy and fixed max capacity.template<typenameT>classstack4#defineBASESprivateboost::contract::constructor_precondition<stack4<T>>:BASES{friendboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Count non-negative.BOOST_CONTRACT_ASSERT(count()<=capacity());// Count bounded.BOOST_CONTRACT_ASSERT(empty()==(count()==0));// Empty if no elem.}public:/* Initialization */// Allocate static from a maximum of n elements.explicitstack4(intn):boost::contract::constructor_precondition<stack4>([&]{BOOST_CONTRACT_ASSERT(n>=0);// Non-negative capacity.}){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()==n);// Capacity set.});capacity_=n;count_=0;array_=newT[n];}// Deep copy via constructor./* implicit */stack4(stack4const&other){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()==other.capacity());BOOST_CONTRACT_ASSERT(count()==other.count());BOOST_CONTRACT_ASSERT_AXIOM(*this==other);});capacity_=other.capacity_;count_=other.count_;array_=newT[other.capacity_];for(inti=0;i<other.count_;++i)array_[i]=other.array_[i];}// Deep copy via assignment.stack4&operator=(stack4const&other){boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(capacity()==other.capacity());BOOST_CONTRACT_ASSERT(count()==other.count());BOOST_CONTRACT_ASSERT_AXIOM(*this==other);});delete[]array_;capacity_=other.capacity_;count_=other.count_;array_=newT[other.capacity_];for(inti=0;i<other.count_;++i)array_[i]=other.array_[i];return*this;}// Destroy this stack.virtual~stack4(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);delete[]array_;}/* Access */// Max number of stack elements.intcapacity()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returncapacity_;}// Number of stack elements.intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returncount_;}// Top element.Tconst&item()const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());// Not empty (i.e., count > 0).});returnarray_[count_-1];}/* Status Report */// Is stack empty?boolempty()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Empty definition.BOOST_CONTRACT_ASSERT(result==(count()==0));});returnresult=(count_==0);}// Is stack full?boolfull()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(// Full definition.result==(count()==capacity()));});returnresult=(count_==capacity_);}/* Element Change */// Add x on top.voidput(Tconst&x){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!full());// Not full.}).postcondition([&]{BOOST_CONTRACT_ASSERT(!empty());// Not empty.BOOST_CONTRACT_ASSERT(item()==x);// Added to top.BOOST_CONTRACT_ASSERT(count()==*old_count+1);// One more.});array_[count_++]=x;}// Remove top element.voidremove(){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());// Not empty (i.e., count > 0).}).postcondition([&]{BOOST_CONTRACT_ASSERT(!full());// Not full.BOOST_CONTRACT_ASSERT(count()==*old_count-1);// One less.});--count_;}/* Friend Helpers */friendbooloperator==(stack4const&left,stack4const&right){boost::contract::checkinv1=boost::contract::public_function(&left);boost::contract::checkinv2=boost::contract::public_function(&right);if(left.count_!=right.count_)returnfalse;for(inti=0;i<left.count_;++i){if(left.array_[i]!=right.array_[i])returnfalse;}returntrue;}private:intcapacity_;intcount_;T*array_;// Internally use C-style array.};#endif// #include guard--Extraspaces,newlines,etc.forvisualalignmentwiththislibrarycode.indexingdestription:"Dispenser with LIFO access policy and a fixed max capacity."classinterfaceSTACK4[G]creationmake--Interfaceonly(noimplementation).invariantcount_non_negative:count>=0count_bounded:count<=capacityempty_if_no_elements:empty=(count=0)feature--Initialization--Allocatestackforamaximumofnelements.make(n:INTEGER)isrequirenon_negative_capacity:n>=0ensurecapacity_set:capacity=nendfeature--Access--Maxnumberofstackelements.capacity:INTEGER--Numberofstackelements.count:INTEGER--Topelement.item:Gisrequirenot_empty:notempty--i.e.,count>0endfeature--Statusreport--Isstackempty?empty:BOOLEANisensureempty_definition:result=(count=0)end--Isstackfull?full:BOOLEANisensurefull_definition:result=(count=capacity)endfeature--Elementchange--Addxontop.put(x:G)isrequirenot_full:notfullensurenot_empty:notemptyadded_to_top:item=xone_more_item:count=oldcount+1end--Removetopelement.removeisrequirenot_empty:notempty--i.e.,count>0ensurenot_full:notfullone_fewer_item:count=oldcount-1endend--classinterfaceSTACK4--End.#include"stack4.hpp"#include<cassert>intmain(){stack4<int>s(3);assert(s.capacity()==3);assert(s.count()==0);assert(s.empty());assert(!s.full());s.put(123);assert(!s.empty());assert(!s.full());assert(s.item()==123);s.remove();assert(s.empty());assert(!s.full());return0;}[Meyer97]
Stack3: Error codes instead of preconditions// File: stack3.cpp#include"stack4.hpp"#include<boost/contract.hpp>#include<boost/optional.hpp>#include<cassert>// Dispenser LIFO with max capacity using error codes.template<typenameT>classstack3{friendclassboost::contract::access;voidinvariant()const{if(!error()){BOOST_CONTRACT_ASSERT(count()>=0);// Count non-negative.BOOST_CONTRACT_ASSERT(count()<=capacity());// Count bounded.// Empty if no element.BOOST_CONTRACT_ASSERT(empty()==(count()==0));}}public:enumerror_code{no_error=0,overflow_error,underflow_error,size_error};/* Initialization */// Create stack for max of n elems, if n < 0 set error (no preconditions).explicitstack3(intn,Tconst&default_value=T()):stack_(0),error_(no_error){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{// Error if impossible.BOOST_CONTRACT_ASSERT((n<0)==(error()==size_error));// No error if possible.BOOST_CONTRACT_ASSERT((n>=0)==!error());// Created if no error.if(!error())BOOST_CONTRACT_ASSERT(capacity()==n);});if(n>=0)stack_=stack4<T>(n);elseerror_=size_error;}/* Access */// Max number of stack elements.intcapacity()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnstack_.capacity();}// Number of stack elements.intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnstack_.count();}// Top element if present, otherwise none and set error (no preconditions).boost::optional<Tconst&>item()const{boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Error if impossible.BOOST_CONTRACT_ASSERT(empty()==(error()==underflow_error));// No error if possible.BOOST_CONTRACT_ASSERT(!empty()==!error());});if(!empty()){error_=no_error;returnboost::optional<Tconst&>(stack_.item());}else{error_=underflow_error;returnboost::optional<Tconst&>();}}/* Status Report */// Error indicator set by various operations.error_codeerror()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnerror_;}boolempty()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnstack_.empty();}boolfull()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnstack_.full();}/* Element Change */// Add x to top if capacity allows, otherwise set error (no preconditions).voidput(Tconst&x){boost::contract::old_ptr<bool>old_full=BOOST_CONTRACT_OLDOF(full());boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Error if impossible.BOOST_CONTRACT_ASSERT(*old_full==(error()==overflow_error));// No error if possible.BOOST_CONTRACT_ASSERT(!*old_full==!error());if(!error()){// If no error...BOOST_CONTRACT_ASSERT(!empty());// ...not empty.BOOST_CONTRACT_ASSERT(*item()==x);// ...added to top.// ...one more.BOOST_CONTRACT_ASSERT(count()==*old_count+1);}});if(full())error_=overflow_error;else{stack_.put(x);error_=no_error;}}// Remove top element if possible, otherwise set error (no preconditions).voidremove(){boost::contract::old_ptr<bool>old_empty=BOOST_CONTRACT_OLDOF(empty());boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Error if impossible.BOOST_CONTRACT_ASSERT(*old_empty==(error()==underflow_error));// No error if possible.BOOST_CONTRACT_ASSERT(!*old_empty==!error());if(!error()){// If no error...BOOST_CONTRACT_ASSERT(!full());// ...not full.// ...one less.BOOST_CONTRACT_ASSERT(count()==*old_count-1);}});if(empty())error_=underflow_error;else{stack_.remove();error_=no_error;}}private:stack4<T>stack_;mutableerror_codeerror_;};intmain(){stack3<int>s(3);assert(s.capacity()==3);assert(s.count()==0);assert(s.empty());assert(!s.full());s.put(123);assert(!s.empty());assert(!s.full());assert(*s.item()==123);s.remove();assert(s.empty());assert(!s.full());return0;}[Mitchell02]
Name List: Relaxed subcontracts#include<boost/contract.hpp>#include<string>#include<vector>#include<algorithm>#include<cassert>// List of names.classname_list{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Non-negative count.}public:/* Creation */// Create an empty list.name_list(){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==0);// Empty list.});}// Destroy list.virtual~name_list(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Basic Queries */// Number of names in list.intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnnames_.size();}// Is name in list?boolhas(std::stringconst&name)const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// If empty, has not.if(count()==0)BOOST_CONTRACT_ASSERT(!result);});returnresult=names_.cend()!=std::find(names_.cbegin(),names_.cend(),name);}/* Commands */// Add name to list, if name not already in list.virtualvoidput(std::stringconst&name,boost::contract::virtual_*v=0){boost::contract::old_ptr<bool>old_has_name=BOOST_CONTRACT_OLDOF(v,has(name));boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(v,count());boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(!has(name));// Not already in list.}).postcondition([&]{if(!*old_has_name){// If-guard allows to relax subcontracts.BOOST_CONTRACT_ASSERT(has(name));// Name in list.BOOST_CONTRACT_ASSERT(count()==*old_count+1);// Inc.}});names_.push_back(name);}private:std::vector<std::string>names_;};classrelaxed_name_list#defineBASESpublicname_list:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Subcontracting.#undefBASESBOOST_CONTRACT_OVERRIDE(put);public:/* Commands */// Add name to list, or do nothing if name already in list (relaxed).voidput(std::stringconst&name,boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<bool>old_has_name=BOOST_CONTRACT_OLDOF(v,has(name));boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(v,count());boost::contract::checkc=boost::contract::public_function<override_put>(v,&relaxed_name_list::put,this,name).precondition([&]{// Relax inherited preconditions.BOOST_CONTRACT_ASSERT(has(name));// Already in list.}).postcondition([&]{// Inherited post. not checked given if-guard.if(*old_has_name){// Count unchanged if name already in list.BOOST_CONTRACT_ASSERT(count()==*old_count);}});if(!has(name))name_list::put(name);// Else, do nothing.}};intmain(){std::stringconstjs="John Smith";relaxed_name_listrl;rl.put(js);assert(rl.has(js));rl.put(js);// OK, relaxed contracts allow calling this again (do nothing).name_listnl;nl.put(js);assert(nl.has(js));// nl.put(js); // Error, contracts do not allow calling this again.return0;}[Mitchell02]
Dictionary: Key-value map#include<boost/contract.hpp>#include<utility>#include<map>#include<cassert>template<typenameK,typenameT>classdictionary{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Non-negative count.}public:/* Creation */// Create empty dictionary.dictionary(){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==0);// Empty.});}// Destroy dictionary.virtual~dictionary(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Basic Queries */// Number of key entries.intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnitems_.size();}// Has entry for key?boolhas(Kconst&key)const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Empty has no key.if(count()==0)BOOST_CONTRACT_ASSERT(!result);});returnresult=(items_.find(key)!=items_.end());}// Value for a given key.Tconst&value_for(Kconst&key)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(has(key));// Has key.});// Find != end because of precondition (no defensive programming).returnitems_.find(key)->second;}/* Commands */// Add value of a given key.voidput(Kconst&key,Tconst&value){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!has(key));// Has not key already.}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count+1);// Count inc.BOOST_CONTRACT_ASSERT(has(key));// Has key.// Value set for key.BOOST_CONTRACT_ASSERT(value_for(key)==value);});items_.insert(std::make_pair(key,value));}// Remove value for given key.voidremove(Kconst&key){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(has(key));// Has key.}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count-1);// Count dec.BOOST_CONTRACT_ASSERT(!has(key));// Has not key.});items_.erase(key);}private:std::map<K,T>items_;};intmain(){std::stringconstjs="John Smith";dictionary<std::string,int>ages;assert(!ages.has(js));ages.put(js,23);assert(ages.value_for(js)==23);ages.remove(js);assert(ages.count()==0);return0;}[Mitchell02]
Courier: Subcontracting and static class invariants#include<boost/contract.hpp>#include<string>#include<cassert>structpackage{doubleweight_kg;std::stringlocation;doubleaccepted_hour;doubledelivered_hour;explicitpackage(double_weight_kg,std::stringconst&_location="",double_accepted_hour=0.0,double_delivered_hour=0.0):weight_kg(_weight_kg),location(_location),accepted_hour(_accepted_hour),delivered_hour(_delivered_hour){}};// Courier for package delivery.classcourier#defineBASESprivateboost::contract::constructor_precondition<courier>:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESstaticvoidstatic_invariant(){// Positive min. insurance.BOOST_CONTRACT_ASSERT(min_insurance_usd>=0.0);}voidinvariant()const{// Above min. insurance.BOOST_CONTRACT_ASSERT(insurance_cover_usd()>=min_insurance_usd);}public:staticdoublemin_insurance_usd;/* Creation */// Create courier with specified insurance value.explicitcourier(double_insurance_cover_usd=min_insurance_usd):boost::contract::constructor_precondition<courier>([&]{// Positive insurance.BOOST_CONTRACT_ASSERT(_insurance_cover_usd>=0.0);}),insurance_cover_usd_(_insurance_cover_usd){// Check invariants.boost::contract::checkc=boost::contract::constructor(this);}// Destroy courier.virtual~courier(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Queries */// Return insurance cover.doubleinsurance_cover_usd()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returninsurance_cover_usd_;}/* Commands */// Deliver package to destination.virtualvoiddeliver(package&package_delivery,std::stringconst&destination,boost::contract::virtual_*v=0){boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{// Within max weight of this delivery.BOOST_CONTRACT_ASSERT(package_delivery.weight_kg<5.0);}).postcondition([&]{// Within max delivery type.BOOST_CONTRACT_ASSERT(double(package_delivery.delivered_hour-package_delivery.accepted_hour)<=3.0);// Delivered at destination.BOOST_CONTRACT_ASSERT(package_delivery.location==destination);});package_delivery.location=destination;// Delivery takes 2.5 hours.package_delivery.delivered_hour=package_delivery.accepted_hour+2.5;}private:doubleinsurance_cover_usd_;};doublecourier::min_insurance_usd=10.0e+6;// Different courier for package delivery.classdifferent_courier#defineBASESprivateboost::contract::constructor_precondition<\different_courier>,publiccourier:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Subcontracting.#undefBASESstaticvoidstatic_invariant(){BOOST_CONTRACT_ASSERT(// Better insurance amount.different_insurance_usd>=courier::min_insurance_usd);}voidinvariant()const{// Above different insurance value.BOOST_CONTRACT_ASSERT(insurance_cover_usd()>=different_insurance_usd);}BOOST_CONTRACT_OVERRIDE(deliver)public:staticdoubledifferent_insurance_usd;/* Creation */// Create courier with specified insurance value.explicitdifferent_courier(doubleinsurance_cover_usd=different_insurance_usd):boost::contract::constructor_precondition<different_courier>([&]{// Positive insurance value.BOOST_CONTRACT_ASSERT(insurance_cover_usd>0.0);}),courier(insurance_cover_usd){// Check invariants.boost::contract::checkc=boost::contract::constructor(this);}// Destroy courier.virtual~different_courier(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Commands */virtualvoiddeliver(package&package_delivery,std::stringconst&destination,boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_deliver>(v,&different_courier::deliver,this,package_delivery,destination).precondition([&]{// Package can weight more (weaker precondition).BOOST_CONTRACT_ASSERT(package_delivery.weight_kg<=8.0);}).postcondition([&]{// Faster delivery (stronger postcondition).BOOST_CONTRACT_ASSERT(double(package_delivery.delivered_hour-package_delivery.accepted_hour)<=2.0);// Inherited "delivery at destination" postcondition.});package_delivery.location=destination;// Delivery takes 0.5 hours.package_delivery.delivered_hour=package_delivery.accepted_hour+0.5;}};doubledifferent_courier::different_insurance_usd=20.0e+6;intmain(){packagecups(3.6,"store");courierc;c.deliver(cups,"home");assert(cups.location=="home");packagedesk(7.2,"store");different_courierdc;dc.deliver(desk,"office");assert(desk.location=="office");return0;}[Mitchell02]
Stack: Stack-like container#include<boost/contract.hpp>#include<boost/optional.hpp>#include<vector>#include<cassert>template<typenameT>classstack{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Non-negative count.}public:/* Creation */// Create empty stack.stack(){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==0);// Empty.});}// Destroy stack.virtual~stack(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Basic Queries */// Number of items.intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnitems_.size();}// Item at index in [1, count()] (as in Eiffel).Tconst&item_at(intindex)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(index>0);// Positive index.BOOST_CONTRACT_ASSERT(index<=count());// Index within count.});returnitems_[index-1];}/* Derived Queries */// If no items.boolis_empty()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Consistent with count.BOOST_CONTRACT_ASSERT(result==(count()==0));});returnresult=(count()==0);}// Top item.Tconst&item()const{boost::optional<Tconst&>result;// Avoid extra construction of T.boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count()>0);// Not empty.}).postcondition([&]{// Item on top.BOOST_CONTRACT_ASSERT(*result==item_at(count()));});return*(result=item_at(count()));}/* Commands */// Push item to the top.voidput(Tconst&new_item){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count+1);// Count inc.BOOST_CONTRACT_ASSERT(item()==new_item);// Item set.});items_.push_back(new_item);}// Pop top item.voidremove(){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count()>0);// Not empty.}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count-1);// Count dec.});items_.pop_back();}private:std::vector<T>items_;};intmain(){stack<int>s;assert(s.count()==0);s.put(123);assert(s.item()==123);s.remove();assert(s.is_empty());return0;}[Mitchell02]
Simple Queue: Queue-like container and disable old value copies for audit assertions#include<boost/contract.hpp>#include<boost/optional.hpp>#include<vector>#include<cassert>template<typenameT>classsimple_queue#defineBASESprivateboost::contract::constructor_precondition<\simple_queue<T>>:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Non-negative count.}public:/* Creation */// Create empty queue.explicitsimple_queue(inta_capacity):boost::contract::constructor_precondition<simple_queue>([&]{BOOST_CONTRACT_ASSERT(a_capacity>0);// Positive capacity.}){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{// Capacity set.BOOST_CONTRACT_ASSERT(capacity()==a_capacity);BOOST_CONTRACT_ASSERT(is_empty());// Empty.});items_.reserve(a_capacity);}// Destroy queue.virtual~simple_queue(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Basic Queries */// Items in queue (in their order).// (Somewhat exposes implementation but allows to check more contracts.)std::vector<T>const&items()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnitems_;}// Max number of items queue can hold.intcapacity()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnitems_.capacity();}/* Derived Queries */// Number of items.intcount()const{intresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Return items count.BOOST_CONTRACT_ASSERT(result==int(items().size()));});returnresult=items_.size();}// Item at head.Tconst&head()const{boost::optional<Tconst&>result;boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!is_empty());// Not empty.}).postcondition([&]{// Return item on top.BOOST_CONTRACT_ASSERT(*result==items().at(0));});return*(result=items_.at(0));}// If queue contains no item.boolis_empty()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{// Consistent with count.BOOST_CONTRACT_ASSERT(result==(count()==0));});returnresult=(items_.size()==0);}// If queue has no room for another item.boolis_full()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(// Consistent with size and capacity.result==(capacity()==int(items().size())));});returnresult=(items_.size()==items_.capacity());}/* Commands */// Remove head itme and shift all other items.voidremove(){// Expensive all_equal postcond. and old_items copy might be skipped.boost::contract::old_ptr<std::vector<T>>old_items;#ifdefBOOST_CONTRACT_AUDIITS=BOOST_CONTRACT_OLDOF(items())#endif// Else, leave old pointer null...;boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!is_empty());// Not empty.}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count-1);// Count dec.// ...following skipped #ifndef AUDITS.if(old_items)all_equal(items(),*old_items,/* shifted = */1);});items_.erase(items_.begin());}// Add item to tail.voidput(Tconst&item){// Expensive all_equal postcond. and old_items copy might be skipped.boost::contract::old_ptr<std::vector<T>>old_items;#ifdefBOOST_CONTRACT_AUDITS=BOOST_CONTRACT_OLDOF(items())#endif// Else, leave old pointer null...;boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count()<capacity());// Room for add.}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count+1);// Count inc.// Second to last item.BOOST_CONTRACT_ASSERT(items().at(count()-1)==item);// ...following skipped #ifndef AUDITS.if(old_items)all_equal(items(),*old_items);});items_.push_back(item);}private:// Contract helper.staticboolall_equal(std::vector<T>const&left,std::vector<T>const&right,unsignedoffset=0){boost::contract::checkc=boost::contract::function().precondition([&]{// Correct offset.BOOST_CONTRACT_ASSERT(right.size()==left.size()+offset);});for(unsignedi=offset;i<right.size();++i){if(left.at(i-offset)!=right.at(i))returnfalse;}returntrue;}std::vector<T>items_;};intmain(){simple_queue<int>q(10);q.put(123);q.put(456);assert(q.capacity()==10);assert(q.head()==123);assert(!q.is_empty());assert(!q.is_full());std::vector<int>const&items=q.items();assert(items.at(0)==123);assert(items.at(1)==456);q.remove();assert(q.count()==1);return0;}[Mitchell02]
Customer Manager: Contracts instead of defensive programming#include<boost/contract.hpp>#include<string>#include<map>#include<utility>#include<cassert>// Basic customer information.structcustomer_info{friendclasscustomer_manager;typedefstd::stringidentifier;identifierid;explicitcustomer_info(identifierconst&_id):id(_id),name_(),address_(),birthday_(){}private:std::stringname_;std::stringaddress_;std::stringbirthday_;};// Manage customers.classcustomer_manager{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(count()>=0);// Non-negative count.}public:/* Creation */customer_manager(){// Check invariants.boost::contract::checkc=boost::contract::constructor(this);}virtual~customer_manager(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}/* Basic Queries */intcount()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returncustomers_.size();}boolid_active(customer_info::identifierconst&id)const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returncustomers_.find(id)!=customers_.cend();}/* Derived Queries */std::stringconst&name_for(customer_info::identifierconst&id)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(id_active(id));// Active.});// Find != end because of preconditions (no defensive programming).returncustomers_.find(id)->second.name_;}/* Commands */voidadd(customer_infoconst&info){boost::contract::old_ptr<int>old_count=BOOST_CONTRACT_OLDOF(count());boost::contract::checkc=boost::contract::public_function(this).precondition([&]{// Not already active.BOOST_CONTRACT_ASSERT(!id_active(info.id));}).postcondition([&]{BOOST_CONTRACT_ASSERT(count()==*old_count+1);// Count inc.BOOST_CONTRACT_ASSERT(id_active(info.id));// Activated.});customers_.insert(std::make_pair(info.id,customer(info)));}voidset_name(customer_info::identifierconst&id,std::stringconst&name){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(id_active(id));// Already active.}).postcondition([&]{BOOST_CONTRACT_ASSERT(name_for(id)==name);// Name set.});// Find != end because of precondition (no defensive programming).customers_.find(id)->second.name_=name;}private:classagent{};// Customer agent.structcustomer:customer_info{agentmanaging_agent;std::stringlast_contact;explicitcustomer(customer_infoconst&info):customer_info(info),managing_agent(),last_contact(){}};std::map<customer_info::identifier,customer>customers_;};intmain(){customer_managerm;customer_infoconstjs("john_smith_123");m.add(js);m.set_name(js.id,"John Smith");assert(m.name_for(js.id)=="John Smith");assert(m.count()==1);assert(m.id_active(js.id));return0;}[Mitchell02]
Observer: Pure virtual functions#ifndefOBSERVER_HPP_#defineOBSERVER_HPP_#include<boost/contract.hpp>#include<cassert>// Observer.classobserver{friendclasssubject;public:// No inv and no bases so contracts optional if no pre, post, and override./* Creation */observer(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::constructor(this);}virtual~observer(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}/* Commands */// If up-to-date with related subject.virtualboolup_to_date_with_subject(boost::contract::virtual_*v=0)const=0;// Update this observer.virtualvoidupdate(boost::contract::virtual_*v=0)=0;};boolobserver::up_to_date_with_subject(boost::contract::virtual_*v)const{boost::contract::checkc=boost::contract::public_function(v,this);assert(false);returnfalse;}voidobserver::update(boost::contract::virtual_*v){boost::contract::checkc=boost::contract::public_function(v,this).postcondition([&]{BOOST_CONTRACT_ASSERT(up_to_date_with_subject());// Up-to-date.});assert(false);}#endif// #include guard#ifndefSUBJECT_HPP_#defineSUBJECT_HPP_#include"observer.hpp"#include<boost/contract.hpp>#include<vector>#include<algorithm>#include<cassert>// Subject for observer design pattern.classsubject{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT_AUDIT(all_observers_valid(observers()));// Valid.}public:/* Creation */// Construct subject with no observer.subject(){// Check invariant.boost::contract::checkc=boost::contract::constructor(this);}// Destroy subject.virtual~subject(){// Check invariant.boost::contract::checkc=boost::contract::destructor(this);}/* Queries */// If given object is attached.boolattached(observerconst*ob)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(ob);// Not null.});returnstd::find(observers_.cbegin(),observers_.cend(),ob)!=observers_.cend();}/* Commands */// Attach given object as an observer.voidattach(observer*ob){boost::contract::old_ptr<std::vector<observerconst*>>old_observers;#ifdefBOOST_CONTRACT_AUDITSold_observers=BOOST_CONTRACT_OLDOF(observers());#endifboost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(ob);// Not null.BOOST_CONTRACT_ASSERT(!attached(ob));// Not already attached.}).postcondition([&]{BOOST_CONTRACT_ASSERT(attached(ob));// Attached.// Others not changed (frame rule).BOOST_CONTRACT_ASSERT_AUDIT(other_observers_unchanged(*old_observers,observers(),ob));});observers_.push_back(ob);}protected:// Contracts could have been omitted for protected/private with no pre/post./* Queries */// All observers attached to this subject.std::vector<observerconst*>observers()const{std::vector<observerconst*>obs;for(std::vector<observer*>::const_iteratori=observers_.cbegin();i!=observers_.cend();++i){obs.push_back(*i);}returnobs;}/* Commands */// Update all attached observers.voidnotify(){// Protected members use `function` (no inv and no subcontracting).boost::contract::checkc=boost::contract::function().postcondition([&]{// All updated.BOOST_CONTRACT_ASSERT_AUDIT(all_observers_updated(observers()));});for(std::vector<observer*>::iteratori=observers_.begin();i!=observers_.end();++i){// Class invariants ensure no null pointers in observers but class// invariants not checked for non-public functions so assert here.assert(*i);// Pointer not null (defensive programming).(*i)->update();}}private:/* Contract Helpers */staticboolall_observers_valid(std::vector<observerconst*>const&obs){for(std::vector<observerconst*>::const_iteratori=obs.cbegin();i!=obs.cend();++i){if(!*i)returnfalse;}returntrue;}staticboolother_observers_unchanged(std::vector<observerconst*>const&old_obs,std::vector<observerconst*>const&new_obs,observerconst*ob){// Private members use `function` (no inv and no subcontracting).boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(ob);// Not null.});std::vector<observerconst*>remaining=new_obs;std::remove(remaining.begin(),remaining.end(),ob);std::vector<observerconst*>::const_iteratorremaining_it=remaining.begin();std::vector<observerconst*>::const_iteratorold_it=old_obs.begin();while(remaining.cend()!=remaining_it&&old_obs.cend()!=old_it){if(*remaining_it!=*old_it)returnfalse;++remaining_it;++old_it;}returntrue;}staticboolall_observers_updated(std::vector<observerconst*>const&obs){for(std::vector<observerconst*>::const_iteratori=obs.cbegin();i!=obs.cend();++i){if(!*i)returnfalse;if(!(*i)->up_to_date_with_subject())returnfalse;}returntrue;}std::vector<observer*>observers_;};#endif// #include guard#include"observer/observer.hpp"#include"observer/subject.hpp"#include<boost/contract.hpp>#include<cassert>inttest_state;// For testing only.// Implement an actual subject.classconcrete_subject#defineBASESpublicsubject:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Subcontracting.#undefBASESpublic:typedefintstate;// Some state being observed.concrete_subject():state_(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::constructor(this);}virtual~concrete_subject(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}voidset_state(stateconst&new_state){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::public_function(this);state_=new_state;assert(state_==test_state);notify();// Notify all observers.}stateget_state()const{// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::public_function(this);returnstate_;}private:statestate_;};// Implement an actual observer.classconcrete_observer#defineBASESpublicobserver:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Subcontracting.#undefBASESBOOST_CONTRACT_OVERRIDES(up_to_date_with_subject,update)public:// Create concrete observer.explicitconcrete_observer(concrete_subjectconst&subj):subject_(subj),observed_state_(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::constructor(this);}virtual~concrete_observer(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}// Implement base virtual functions.boolup_to_date_with_subject(boost::contract::virtual_*v=0)const/* override */{boolresult;boost::contract::checkc=boost::contract::public_function<override_up_to_date_with_subject>(v,result,&concrete_observer::up_to_date_with_subject,this);returnresult=true;// For simplicity, assume always up-to-date.}voidupdate(boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_update>(v,&concrete_observer::update,this);observed_state_=subject_.get_state();assert(observed_state_==test_state);}private:concrete_subjectconst&subject_;concrete_subject::stateobserved_state_;};intmain(){concrete_subjectsubj;concrete_observerob(subj);subj.attach(&ob);subj.set_state(test_state=123);subj.set_state(test_state=456);return0;}[Mitchell02]
Counter: Subcontracting#ifndefPUSH_BUTTON_HPP_#definePUSH_BUTTON_HPP_#include<boost/contract.hpp>#include<cassert>classpush_button{public:// No inv and no bases so contracts optional if no pre, post, and override./* Creation */// Create an enabled button.push_button():enabled_(true){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(enabled());// Enabled.});}// Destroy button.virtual~push_button(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}/* Queries */// If button is enabled.boolenabled()const{// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::public_function(this);returnenabled_;}/* Commands */// Enable button.voidenable(){boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(enabled());// Enabled.});enabled_=true;}// Disable button.voiddisable(){boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(!enabled());// Disabled.});enabled_=false;}// Invoke externally when button clicked.virtualvoidon_bn_clicked(boost::contract::virtual_*v=0)=0;private:boolenabled_;};voidpush_button::on_bn_clicked(boost::contract::virtual_*v){boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(enabled());// Enabled.});assert(false);}#endif// #include guard#ifndefDECREMENT_BUTTON_HPP_#defineDECREMENT_BUTTON_HPP_#include"push_button.hpp"#include"counter.hpp"#include"../observer/observer.hpp"#include<boost/contract.hpp>#include<boost/noncopyable.hpp>classdecrement_button#defineBASESpublicpush_button,publicobserver,\privateboost::noncopyable:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_OVERRIDES(on_bn_clicked,up_to_date_with_subject,update);public:/* Creation */explicitdecrement_button(counter&a_counter):counter_(a_counter){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{// Enable iff positive value.BOOST_CONTRACT_ASSERT(enabled()==(a_counter.value()>0));});counter_.attach(this);}// Destroy button.virtual~decrement_button(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}/* Commands */virtualvoidon_bn_clicked(boost::contract::virtual_*v=0)/* override */{boost::contract::old_ptr<int>old_value=BOOST_CONTRACT_OLDOF(v,counter_.value());boost::contract::checkc=boost::contract::public_function<override_on_bn_clicked>(v,&decrement_button::on_bn_clicked,this).postcondition([&]{// Counter decremented.BOOST_CONTRACT_ASSERT(counter_.value()==*old_value-1);});counter_.decrement();}virtualboolup_to_date_with_subject(boost::contract::virtual_*v=0)const/* override */{boolresult;boost::contract::checkc=boost::contract::public_function<override_up_to_date_with_subject>(v,result,&decrement_button::up_to_date_with_subject,this);returnresult=true;// For simplicity, assume always up-to-date.}virtualvoidupdate(boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_update>(v,&decrement_button::update,this).postcondition([&]{// Enabled iff positive value.BOOST_CONTRACT_ASSERT(enabled()==(counter_.value()>0));});if(counter_.value()==0)disable();elseenable();}private:counter&counter_;};#endif// #include guard#ifndefCOUNTER_HPP_#defineCOUNTER_HPP_#include"../observer/subject.hpp"#include<boost/contract.hpp>classcounter#defineBASESpublicsubject:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESpublic:/* Creation */// Construct counter with specified value.explicitcounter(inta_value=10):value_(a_value){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(value()==a_value);// Value set.});}// Destroy counter.virtual~counter(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}/* Queries */// Current counter value.intvalue()const{// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::public_function(this);returnvalue_;}/* Commands */// Decrement counter value.voiddecrement(){boost::contract::old_ptr<int>old_value=BOOST_CONTRACT_OLDOF(value());boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(value()==*old_value-1);// Decrement.});--value_;notify();// Notify all attached observers.}private:intvalue_;};#endif// #include guard#include"counter/counter.hpp"#include"counter/decrement_button.hpp"#include"observer/observer.hpp"#include<cassert>inttest_counter;classview_of_counter#defineBASESpublicobserver:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_OVERRIDES(up_to_date_with_subject,update)public:/* Creation */// Create view associated with given counter.explicitview_of_counter(counter&a_counter):counter_(a_counter){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::constructor(this);counter_.attach(this);assert(counter_.value()==test_counter);}// Destroy view.virtual~view_of_counter(){// Could have omitted contracts here (nothing to check).boost::contract::checkc=boost::contract::destructor(this);}/* Commands */virtualboolup_to_date_with_subject(boost::contract::virtual_*v=0)const/* override */{boolresult;boost::contract::checkc=boost::contract::public_function<override_up_to_date_with_subject>(v,result,&view_of_counter::up_to_date_with_subject,this);returnresult=true;// For simplicity, assume always up-to-date.}virtualvoidupdate(boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_update>(v,&view_of_counter::update,this);assert(counter_.value()==test_counter);}private:counter&counter_;};intmain(){countercnt(test_counter=1);view_of_counterview(cnt);decrement_buttondec(cnt);assert(dec.enabled());test_counter--;dec.on_bn_clicked();assert(!dec.enabled());return0;}[Cline90]
Vector: Comparison with A++ proposal syntax
This Library
A++ Proposal (never actually implemented)
#ifndefVECTOR_HPP_#defineVECTOR_HPP_#include<boost/contract.hpp>// NOTE: Incomplete contract assertions, addressing only `size`.template<typenameT>classvector#defineBASESprivateboost::contract::constructor_precondition<vector<T>>:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{BOOST_CONTRACT_ASSERT(size()>=0);}public:explicitvector(intcount=10):boost::contract::constructor_precondition<vector>([&]{BOOST_CONTRACT_ASSERT(count>=0);}),data_(newT[count]),size_(count){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);});for(inti=0;i<size_;++i)data_[i]=T();}virtual~vector(){boost::contract::checkc=boost::contract::destructor(this);delete[]data_;}intsize()const{boost::contract::checkc=boost::contract::public_function(this);returnsize_;// Non-negative result already checked by invariant.}voidresize(intcount){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(count>=0);}).postcondition([&]{BOOST_CONTRACT_ASSERT(size()==count);});T*slice=newT[count];for(inti=0;i<count&&i<size_;++i)slice[i]=data_[i];delete[]data_;data_=slice;size_=count;}T&operator[](intindex){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(index>=0);BOOST_CONTRACT_ASSERT(index<size());});returndata_[index];}Tconst&operator[](intindex)const{boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(index>=0);BOOST_CONTRACT_ASSERT(index<size());});returndata_[index];}private:T*data_;intsize_;};#endif// #include guard// Extra spaces, newlines, etc. for visual alignment with this library code.template<typenameT>classvector{legal:// Class invariants (legal).size()>=0;public:explicitvector(intcount=10):data_(newT[count]),size_(count){for(inti=0;i<size_;++i)data_[i]=T();}virtual~vector(){delete[]data_;}intsize()const{returnsize_;}voidresize(intcount){T*slice=newT[count];for(inti=0;i<count&&i<size_;++i)slice[i]=data_[i];delete[]data_;data_=slice;size_=count;}T&operator[](intindex){returndata_[index];}T&operator[](intindex)const{returndata_[index];}axioms:// Preconditions (require) and postconditions (promise) for each func.[intcount;requirecount>=0;promisesize()==count]vector(count);[intcount;requirecount>=0;promisesize()==count]resize(count);[intindex;requireindex>=0&&index<size()](*this)[x];// Op[].[intindex;requireindex>=0&&index<size()](*this)[x]const;// Op[].private:T*data_;intsize_;};// End.#include"vector.hpp"#include<cassert>intmain(){vector<int>v(3);assert(v.size()==3);v[0]=123;v.resize(2);assert(v[0]==123);assert(v.size()==2);return0;}[Cline90]
Stack: Stack-like container#include<boost/contract.hpp>#include<cassert>// NOTE: Incomplete contract assertions, addressing only `empty` and `full`.template<typenameT>classstack#defineBASESprivateboost::contract::constructor_precondition<stack<T>>:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESpublic:explicitstack(intcapacity):boost::contract::constructor_precondition<stack>([&]{BOOST_CONTRACT_ASSERT(capacity>=0);}),data_(newT[capacity]),capacity_(capacity),size_(0){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(empty());BOOST_CONTRACT_ASSERT(full()==(capacity==0));});for(inti=0;i<capacity_;++i)data_[i]=T();}virtual~stack(){boost::contract::checkc=boost::contract::destructor(this);delete[]data_;}boolempty()const{boost::contract::checkc=boost::contract::public_function(this);returnsize_==0;}boolfull()const{boost::contract::checkc=boost::contract::public_function(this);returnsize_==capacity_;}voidpush(Tconst&value){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!full());}).postcondition([&]{BOOST_CONTRACT_ASSERT(!empty());});data_[size_++]=value;}Tpop(){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());}).postcondition([&]{BOOST_CONTRACT_ASSERT(!full());});returndata_[--size_];}private:T*data_;intcapacity_;intsize_;};intmain(){stack<int>s(3);s.push(123);assert(s.pop()==123);return0;}[Cline90]
Vector-Stack: Subcontracting#include"vector.hpp"#include<boost/contract.hpp>#include<boost/optional.hpp>#include<cassert>// NOTE: Incomplete contract assertions, addressing only `empty` and `full`.template<typenameT>classabstract_stack{public:abstract_stack(){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{// AXIOM as empty() cannot actually be checked here to avoid// calling pure virtual function length() during construction).BOOST_CONTRACT_ASSERT_AXIOM(empty());});}virtual~abstract_stack(){boost::contract::checkc=boost::contract::destructor(this);}boolfull()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result==(length()==capacity()));});returnresult=(length()==capacity());}boolempty()const{boolresult;boost::contract::checkc=boost::contract::public_function(this).postcondition([&]{BOOST_CONTRACT_ASSERT(result=(length()==0));});returnresult=(length()==0);}virtualintlength(boost::contract::virtual_*v=0)const=0;virtualintcapacity(boost::contract::virtual_*v=0)const=0;virtualTconst&item(boost::contract::virtual_*v=0)const=0;virtualvoidpush(Tconst&value,boost::contract::virtual_*v=0)=0;virtualTconst&pop(boost::contract::virtual_*v=0)=0;virtualvoidclear(boost::contract::virtual_*v=0)=0;};template<typenameT>intabstract_stack<T>::length(boost::contract::virtual_*v)const{intresult;boost::contract::checkc=boost::contract::public_function(v,result,this).postcondition([&](intconst&result){BOOST_CONTRACT_ASSERT(result>=0);});assert(false);returnresult;}template<typenameT>intabstract_stack<T>::capacity(boost::contract::virtual_*v)const{intresult;boost::contract::checkc=boost::contract::public_function(v,result,this).postcondition([&](intconst&result){BOOST_CONTRACT_ASSERT(result>=0);});assert(false);returnresult;}template<typenameT>Tconst&abstract_stack<T>::item(boost::contract::virtual_*v)const{boost::optional<Tconst&>result;boost::contract::checkc=boost::contract::public_function(v,result,this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());});assert(false);return*result;}template<typenameT>voidabstract_stack<T>::push(Tconst&value,boost::contract::virtual_*v){boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{BOOST_CONTRACT_ASSERT(!full());}).postcondition([&]{BOOST_CONTRACT_ASSERT(!empty());});assert(false);}template<typenameT>Tconst&abstract_stack<T>::pop(boost::contract::virtual_*v){boost::optional<Tconst&>result;boost::contract::old_ptr<T>old_item=BOOST_CONTRACT_OLDOF(v,item());boost::contract::checkc=boost::contract::public_function(v,result,this).precondition([&]{BOOST_CONTRACT_ASSERT(!empty());}).postcondition([&](boost::optional<Tconst&>const&result){BOOST_CONTRACT_ASSERT(!full());BOOST_CONTRACT_ASSERT(*result==*old_item);});assert(false);return*result;}template<typenameT>voidabstract_stack<T>::clear(boost::contract::virtual_*v){boost::contract::checkc=boost::contract::public_function(v,this).postcondition([&]{BOOST_CONTRACT_ASSERT(empty());});assert(false);}template<typenameT>classvstack#defineBASESprivateboost::contract::constructor_precondition<\vstack<T>>,publicabstract_stack<T>:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{BOOST_CONTRACT_ASSERT(length()>=0);BOOST_CONTRACT_ASSERT(length()<capacity());}BOOST_CONTRACT_OVERRIDES(length,capacity,item,push,pop,clear)public:explicitvstack(intcount=10):boost::contract::constructor_precondition<vstack>([&]{BOOST_CONTRACT_ASSERT(count>=0);}),vect_(count),// OK, executed after precondition so count >= 0.len_(0){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(length()==0);BOOST_CONTRACT_ASSERT(capacity()==count);});}virtual~vstack(){boost::contract::checkc=boost::contract::destructor(this);}// Inherited from abstract_stack.virtualintlength(boost::contract::virtual_*v=0)const/* override */{intresult;boost::contract::checkc=boost::contract::public_function<override_length>(v,result,&vstack::length,this);returnresult=len_;}virtualintcapacity(boost::contract::virtual_*v=0)const/* override */{intresult;boost::contract::checkc=boost::contract::public_function<override_capacity>(v,result,&vstack::capacity,this);returnresult=vect_.size();}virtualTconst&item(boost::contract::virtual_*v=0)const/* override */{boost::optional<Tconst&>result;boost::contract::checkc=boost::contract::public_function<override_item>(v,result,&vstack::item,this);return*(result=vect_[len_-1]);}virtualvoidpush(Tconst&value,boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_push>(v,&vstack::push,this,value);vect_[len_++]=value;}virtualTconst&pop(boost::contract::virtual_*v=0)/* override */{boost::optional<Tconst&>result;boost::contract::checkc=boost::contract::public_function<override_pop>(v,result,&vstack::pop,this);return*(result=vect_[--len_]);}virtualvoidclear(boost::contract::virtual_*v=0)/* override */{boost::contract::checkc=boost::contract::public_function<override_clear>(v,&vstack::clear,this);len_=0;}private:vector<T>vect_;intlen_;};intmain(){vstack<int>s(3);assert(s.capacity()==3);s.push(123);assert(s.length()==1);assert(s.pop()==123);return0;}[Cline90]
Calendar: A very simple calendar#include<boost/contract.hpp>#include<cassert>classcalendar{friendclassboost::contract::access;voidinvariant()const{BOOST_CONTRACT_ASSERT(month()>=1);BOOST_CONTRACT_ASSERT(month()<=12);BOOST_CONTRACT_ASSERT(date()>=1);BOOST_CONTRACT_ASSERT(date()<=days_in(month()));}public:calendar():month_(1),date_(31){boost::contract::checkc=boost::contract::constructor(this).postcondition([&]{BOOST_CONTRACT_ASSERT(month()==1);BOOST_CONTRACT_ASSERT(date()==31);});}virtual~calendar(){// Check invariants.boost::contract::checkc=boost::contract::destructor(this);}intmonth()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returnmonth_;}intdate()const{// Check invariants.boost::contract::checkc=boost::contract::public_function(this);returndate_;}voidreset(intnew_month){boost::contract::checkc=boost::contract::public_function(this).precondition([&]{BOOST_CONTRACT_ASSERT(new_month>=1);BOOST_CONTRACT_ASSERT(new_month<=12);}).postcondition([&]{BOOST_CONTRACT_ASSERT(month()==new_month);});month_=new_month;}private:staticintdays_in(intmonth){intresult;boost::contract::checkc=boost::contract::function().precondition([&]{BOOST_CONTRACT_ASSERT(month>=1);BOOST_CONTRACT_ASSERT(month<=12);}).postcondition([&]{BOOST_CONTRACT_ASSERT(result>=1);BOOST_CONTRACT_ASSERT(result<=31);});returnresult=31;// For simplicity, assume all months have 31 days.}intmonth_,date_;};intmain(){calendarcal;assert(cal.date()==31);assert(cal.month()==1);cal.reset(8);// Set month assert(cal.month()==8);return0;}ReferenceHeader <boost/contract.hpp>Include all header files required by this library at once (for convenience). All header files boost/contract/*.hpp are independent from one another and can be included one-by-one to reduce the amount of code to compile from this library in user code (but this was measured to not make an appreciable difference in compile-time so boost/contract.hpp can be included directly in most cases). Instead the headers boost/contract/core/*.hpp are not independent from other library headers and they are automatically included by the boost/contract/*.hpp headers (so the boost/contract/core/*.hpp headers are usually not directly included by programmers).All files under the boost/contract/detail/ directory, names within the boost::contract::detail namespace, names prefixed by boost_contract_detail... and BOOST_CONTRACT_DETAIL... (in any namesapce, including user's code) are reserved for internal use of this library and should never be used directly by programmers.See Also: Getting Started Header <boost/contract/assert.hpp>Assert contract conditions.
BOOST_CONTRACT_ASSERT(cond)
BOOST_CONTRACT_ASSERT_AUDIT(cond)
BOOST_CONTRACT_ASSERT_AXIOM(cond)Macro BOOST_CONTRACT_ASSERT3BOOST_CONTRACT_ASSERTPreferred way to assert contract conditions. // In header: <boost/contract/assert.hpp>
BOOST_CONTRACT_ASSERT(cond)DescriptionAny exception thrown from within a contract (preconditions, postconditions, exception guarantees, old value copies at body, class invariants, etc.) is interpreted by this library as a contract failure. Therefore, users can program contract assertions manually throwing an exception when an asserted condition is checked to be false (this library will then call the appropriate contract failure handler boost::contract::precondition_failure, etc.). However, it is preferred to use this macro because it expands to code that throws boost::contract::assertion_failure with the correct assertion file name (using __FILE__), line number (using __LINE__), and asserted condition code so to produce informative error messages (C++11 __func__ is not used here because in most cases it will simply expand to the internal compiler name of the lambda function used to program the contract conditions adding no specificity to the error message).BOOST_CONTRACT_ASSERT, BOOST_CONTRACT_ASSERT_AUDIT, and BOOST_CONTRACT_ASSERT_AXIOM are the three assertion levels predefined by this library.See Also: Preconditions, Postconditions, Exceptions Guarantees, Class Invariants, No MacrosParameters:condBoolean contract condition to check. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_ASSERT((cond)) will always work.) Macro BOOST_CONTRACT_ASSERT_AUDIT3BOOST_CONTRACT_ASSERT_AUDITPreferred way to assert contract conditions that are computationally expensive, at least compared to the computational cost of executing the function body. // In header: <boost/contract/assert.hpp>
BOOST_CONTRACT_ASSERT_AUDIT(cond)DescriptionThe asserted condition will always be compiled and validated syntactically, but it will not be checked at run-time unless BOOST_CONTRACT_AUDITS is defined (undefined by default). This macro is defined by code equivalent to:#ifdefBOOST_CONTRACT_AUDITS#defineBOOST_CONTRACT_ASSERT_AUDIT(cond) \
BOOST_CONTRACT_ASSERT(cond)#else#defineBOOST_CONTRACT_ASSERT_AUDIT(cond) \
BOOST_CONTRACT_ASSERT(true||cond)#endifBOOST_CONTRACT_ASSERT, BOOST_CONTRACT_ASSERT_AUDIT, and BOOST_CONTRACT_ASSERT_AXIOM are the three assertion levels predefined by this library. If there is a need, programmers are free to implement their own assertion levels defining macros similar to the one above.See Also: Assertion Levels, No MacrosParameters:condBoolean contract condition to check. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_ASSERT_AUDIT((cond)) will always work.) Macro BOOST_CONTRACT_ASSERT_AXIOM3BOOST_CONTRACT_ASSERT_AXIOMPreferred way to document in the code contract conditions that are computationally prohibitive, at least compared to the computational cost of executing the function body. // In header: <boost/contract/assert.hpp>
BOOST_CONTRACT_ASSERT_AXIOM(cond)DescriptionThe asserted condition will always be compiled and validated syntactically, but it will never be checked at run-time. This macro is defined by code equivalent to:#defineBOOST_CONTRACT_ASSERT_AXIOM(cond) \
BOOST_CONTRACT_ASSERT(true||cond)BOOST_CONTRACT_ASSERT, BOOST_CONTRACT_ASSERT_AUDIT, and BOOST_CONTRACT_ASSERT_AXIOM are the three assertion levels predefined by this library. If there is a need, programmers are free to implement their own assertion levels defining macros similar to the one above.See Also: Assertion Levels, No MacrosParameters:condBoolean contract condition to check. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_ASSERT_AXIOM((cond)) will always work.) Header <boost/contract/base_types.hpp>Specify inheritance form base classes (for subcontracting).
BOOST_CONTRACT_BASE_TYPES(...)Macro BOOST_CONTRACT_BASE_TYPES3BOOST_CONTRACT_BASE_TYPESUsed to program the typedef that lists the bases of a derived class. // In header: <boost/contract/base_types.hpp>
BOOST_CONTRACT_BASE_TYPES(...)DescriptionIn order to support subcontracting, a derived class that specifies contracts for one or more overriding public functions must declare a typedef named base_types (or BOOST_CONTRACT_BASES_TYPEDEF) using this macro:classu#defineBASESpublicb,protectedvirtualw1,privatew2:BASES{friendclassboost::contract:access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASES...};This typedef must be public unless boost::contract::access is used.See Also: Base ClassesParameters:...Comma separated list of base classes. Each base must explicitly specify its access specifier public, protected, or private, and also virtual when present (this not always required in C++ instead). There is a limit of about 20 maximum bases that can be listed (because of similar limits in Boost.MPL internally used by this library). This is a variadic macro parameter, on compilers that do not support variadic macros, the typedef for base classes can be programmed manually without using this macro (see No Macros). Header <boost/contract/call_if.hpp>Statically disable compilation and execution of functor calls. These facilities allow to emulate C++17 if constexpr statements when used together with functor templates (and C++14 generic lambdas). Therefore, they are not useful on C++17 compilers where if constexpr can be directly used instead. namespaceboost{namespacecontract{template<bool Pred,typename Then,typename ThenResult =internal_type>struct call_if_statement;template<typename Then>struct call_if_statement<false,Then,internal_type>;template<typename Then>struct call_if_statement<true,Then,internal_type>;template<typename Then,typename ThenResult>struct call_if_statement<true,Then,ThenResult>;template<typename Then>struct call_if_statement<true,Then,void>;template<bool Pred,typename Then>
call_if_statement<Pred,Then>call_if_c(Then);template<typename Pred,typename Then>
call_if_statement<Pred::value,Then>call_if(Then);template<bool Pred,typename Then>boolcondition_if_c(Then,bool=true);template<typename Pred,typename Then>boolcondition_if(Then,bool=true);}}Struct template call_if_statement3boost::contract::call_if_statementSelect compilation and execution of functor template calls using a static boolean predicate (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<bool Pred,typename Then,typename ThenResult =internal_type>struct call_if_statement {};DescriptionThis class template has no members because it is never used directly, it is only used via its specializations. Usually this class template is instantiated only via the return value of boost::contract::call_if and boost::contract::call_if_c.See Also:
Assertion RequirementsTemplate Parametersbool PredStatic boolean predicate that selects which functor template call to compile and execute. typename ThenType of the functor template to call if the static predicate Pred is true. typename ThenResult =internal_typeReturn type of then-branch functor template call (this is usually automatically deduced by this library so it is never explicitly specified by the user, and that is why it is often marked as internal_type in this documentation). Struct template call_if_statement<false, Then, internal_type>3boost::contract::call_if_statement<false, Then, internal_type>Template specialization to handle static predicates that are false (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Then>struct call_if_statement<false,Then,internal_type>{// construct/copy/destructexplicitcall_if_statement(Thenconst&);// public member functionstemplate<typename Else>result_of<Else()>::typeelse_(Else)const;template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<ElseIfPred,ElseIfThen>else_if_c(ElseIfThen)const;template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<ElseIfPred::value,ElseIfThen>else_if(ElseIfThen)const;};DescriptionThis template specialization handles all else-branch functor template calls (whether they return void or not). Usually this class template is instantiated only via the return value of boost::contract::call_if and boost::contract::call_if_c.See Also:
Assertion RequirementsTemplate Parameterstypename ThenType of functor template to call when the static predicate is true (never the case for this template specialization). call_if_statement
public
construct/copy/destructexplicitcall_if_statement(Thenconst& f);Construct this object with the then-branch functor template. Parameters:fThen-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is false). The return type of f() must be the same as (or implicitly convertible to) the return type of all other functor template calls specified for this call-if object. call_if_statement public member functionstemplate<typename Else>result_of<Else()>::typeelse_(Else f)const;Specify the else-branch functor template. The result_of<Else()>::type expression needs be evaluated only when the static predicate is already checked to be false (because Else() is required to compile only in that case). Thus, this result-of expression is evaluated lazily and only in instantiations of this template specialization.Parameters:fElse-branch nullary functor template. The functor template call f() is actually compiled and executed for this template specialization (because the if-statement static predicate is false). The return type of f() must be the same as (or implicitly convertible to) the return type of all other functor template calls specified for this call-if object.Returns:A copy of the value returned by the call to the else-branch functor template f(). template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<ElseIfPred,ElseIfThen>else_if_c(ElseIfThen f)const;Specify an else-if-branch functor template (using a static boolean predicate). Parameters:fElse-if-branch nullary functor template. The functor template call f() is actually compiled and executed if and only if ElseIfPred is true (because the if-statement static predicate is already false for this template specialization). The return type of f() must be the same as (or implicitly convertible to) the return type of all other functor template calls specified for this call-if object.Template Parameters:ElseIfPredStatic boolean predicate selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, this will be the return value of the one functor template call being compiled and executed. template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<ElseIfPred::value,ElseIfThen>else_if(ElseIfThen f)const;Specify an else-if-branch functor template (using a nullary boolen meta-function). Parameters:fElse-if-branch nullary functor template. The functor template call f() is actually compiled and executed if and only if ElseIfPred::value is true (because the if-statement static predicate is already false for this template specialization). The return type of f() must be the same as (or implicitly convertible to) the return type of all other functor template calls specified for this call-if object.Template Parameters:ElseIfPredNullary boolean meta-function selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, this will be the return value of the one functor template call being compiled and executed. Struct template call_if_statement<true, Then, internal_type>3boost::contract::call_if_statement<true, Then, internal_type>Template specialization to dispatch between then-branch functor template calls that return void and the ones that return non-void (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Then>struct call_if_statement<true,Then,internal_type>:public boost::contract::call_if_statement< true, Then, result_of< Then()>::type >
{// construct/copy/destructexplicitcall_if_statement(Then);};DescriptionThe base class is a call-if statement so the else and else-if statements can be specified if needed. Usually this class template is instantiated only via the return value of boost::contract::call_if and boost::contract::call_if_c.The result_of<Then()>::type expression needs be evaluated only when the static predicate is already checked to be true (because Then() is required to compile only in that case). Thus, this template specialization introduces an extra level of indirection necessary for proper lazy evaluation of this result-of expression.See Also:
Assertion RequirementsTemplate Parameterstypename ThenType of functor template to call when the static predicate is true (as it is for this template specialization). call_if_statement
public
construct/copy/destructexplicitcall_if_statement(Then f);Construct this object with the then-branch functor template. Parameters:fThen-branch nullary functor template. The functor template call f() is compiled and called for this template specialization (because the if-statement static predicate is true). The return type of f() must be the same as (or implicitly convertible to) the return type of all other functor template calls specified for this call-if object. Struct template call_if_statement<true, Then, ThenResult>3boost::contract::call_if_statement<true, Then, ThenResult>Template specialization to handle static predicates that are true for then-branch functor template calls that do not return void (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Then,typename ThenResult>struct call_if_statement<true,Then,ThenResult>{// construct/copy/destructexplicitcall_if_statement(Then);// public member functionsoperatorThenResult()const;template<typename Else>ThenResultelse_(Elseconst&)const;template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,ThenResult>else_if_c(ElseIfThenconst&)const;template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,ThenResult>else_if(ElseIfThenconst&)const;};DescriptionUsually this class template is instantiated only via the return value of boost::contract::call_if and boost::contract::call_if_c.See Also:
Assertion RequirementsTemplate Parameterstypename ThenType of functor template to call when the static predicate is true (as it is for this template specialization). typename ThenResultNon-void return type of the then-branch functor template call. call_if_statement
public
construct/copy/destructexplicitcall_if_statement(Then f);Construct this object with the then-branch functor template. Parameters:fThen-branch nullary functor template. The functor template call f() is actually compiled and executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be the same as (or implicitly convertible to) the ThenResult type. call_if_statement public member functionsoperatorThenResult()const;This implicit type conversion returns a copy of the value returned by the call to the then-branch functor template. template<typename Else>ThenResultelse_(Elseconst& f)const;Specify the else-branch functor template. Parameters:fElse-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be the same as (or implicitly convertible to) the ThenResult type.Returns:A copy of the value returned by the call to the then-branch functor template (because the else-branch functor template call is not executed). template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,ThenResult>else_if_c(ElseIfThenconst& f)const;Specify an else-if-branch functor template (using a static boolean predicate). Parameters:fElse-if-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be the same as (or implicitly convertible to) the ThenResult type.Template Parameters:ElseIfPredStatic boolean predicate selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, it will be the return value of the then-branch functor template call for this template specialization (because the if-statement static predicate is true). template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,ThenResult>else_if(ElseIfThenconst& f)const;Specify an else-if-branch functor template (using a nullary boolean meta-function). Parameters:fElse-if-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be the same as (or implicitly convertible to) the ThenResult type.Template Parameters:ElseIfPredNullary boolean meta-function selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, it will be the return value of the then-branch functor template call for this template specialization (because the if-statement static predicate is true). Struct template call_if_statement<true, Then, void>3boost::contract::call_if_statement<true, Then, void>Template specialization to handle static predicates that are true for then-branch functor template calls that return void (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Then>struct call_if_statement<true,Then,void>{// construct/copy/destructexplicitcall_if_statement(Then);// public member functionstemplate<typename Else>voidelse_(Elseconst&)const;template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,void>else_if_c(ElseIfThenconst&)const;template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,void>else_if(ElseIfThenconst&)const;};DescriptionUsually this class template is instantiated only via the return value of boost::contract::call_if and boost::contract::call_if_c.See Also:
Assertion RequirementsTemplate Parameterstypename ThenType of functor template to call when the static predicate if true (as it is for this template specialization). call_if_statement
public
construct/copy/destructexplicitcall_if_statement(Then f);Construct this object with the then-branch functor template. Parameters:fThen-branch nullary functor template. The functor template call f() is actually compiled and executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be void for this template specialization (because the then-branch functor template calls return void). call_if_statement public member functionstemplate<typename Else>voidelse_(Elseconst& f)const;Specify the else-branch functor template. Parameters:fElse-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be void for this template specialization (because the then-branch functor template calls return void). template<bool ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,void>else_if_c(ElseIfThenconst& f)const;Specify an else-if-branch functor template (using a static boolean predicate). Parameters:fElse-if-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be void for this template specialization (because the then-branch functor template calls return void).Template Parameters:ElseIfPredStatic boolean predicate selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, it will return void for this template specialization (because the then-branch functor template calls return void). template<typename ElseIfPred,typename ElseIfThen>
call_if_statement<true,Then,void>else_if(ElseIfThenconst& f)const;Specify an else-if-branch functor template (using a nullary boolean meta-function). Parameters:fElse-if-branch nullary functor template. The functor template call f() is never compiled or executed for this template specialization (because the if-statement static predicate is true). The return type of f() must be void for this template specialization (because the then-branch functor template calls return void).Template Parameters:ElseIfPredNullary boolean meta-function selecting which functor template call to compile and execute.Returns:A call-if statement so the else statement and additional else-if statements can be specified if needed. Eventually, it will return void for this template specialization (because the then-branch functor template calls return void). Function template call_if_c3boost::contract::call_if_cSelect compilation and execution of functor template calls using a static boolean predicate (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<bool Pred,typename Then>
call_if_statement<Pred,Then>call_if_c(Then f);DescriptionCreate a call-if object with the specified then-branch functor template:boost::contract::call_if_c<Pred1>(then_functor_template1).templateelse_if_c<Pred2>(// Optional.then_functor_template2)// Optionally, other `else_if_c` or...// `else_if`..else_(// Optional for `void` functors,else_functor_template// but required for non `void`.)Optional functor templates for else-if-branches and the else-branch can be specified as needed (the else-branch function template is required if f returns non-void).See Also:
Assertion RequirementsParameters:fThen-branch nullary functor template. The functor template call f() is compiled and executed if and only if Pred is true. The return type of other functor template calls specified for this call-if statement (else-branch, else-if-branches, etc.) must be the same as (or implicitly convertible to) the return type of then-branch functor call f().Template Parameters:PredStatic boolean predicate selecting which functor template call to compile and execute.Returns:A call-if statement so else and else-if statements can be specified if needed. Eventually, this will be the return value of the one functor template call being compiled and executed (which could also be void). Function template call_if3boost::contract::call_ifSelect compilation and execution of functor template calls using a nullary boolean meta-function (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Pred,typename Then>
call_if_statement<Pred::value,Then>call_if(Then f);DescriptionThis is equivalent to boost::contract::call_if_c<Pred::value>(f). Create a call-if object with the specified then-branch functor template:boost::contract::call_if<Pred1>(then_functor_template1).templateelse_if<Pred2>(// Optional.then_functor_template2)// Optionally, other `else_if` or...// `else_if_c`..else_(// Optional for `void` functors,else_functor_template// but required for non `void`.)Optional functor templates for else-if-branches and the else-branch can be specified as needed (the else-branch functor template is required if f returns non-void).See Also:
Assertion RequirementsParameters:fThen-branch nullary functor template. The functor template call f() is compiled and executed if and only if Pred::value is true. The return type of other functor template calls specified for this call-if statement (else-branch, else-if-branches, etc.) must be the same as (or implicitly convertible to) the return type of then-branch functor template call f().Template Parameters:PredNullary boolean meta-function selecting which functor template call to compile and execute.Returns:A call-if statement so else and else-if statements can be specified if needed. Eventually, this will be the return value of the one functor template call being compiled and executed (which could also be void). Function template condition_if_c3boost::contract::condition_if_cSelect compilation and execution of a boolean functor template condition using a static boolean predicate (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<bool Pred,typename Then>boolcondition_if_c(Then f,bool else_ =true);DescriptionCompile and execute the nullary boolean functor template call f() if and only if the specified static boolean predicate Pred is true, otherwise trivially return else_ (true by default) at run-time.A call to boost::contract::condition_if_c<Pred>(f, else_) is logically equivalent to boost::contract::call_if_c<Pred>(f, [] { return else_; }) (but its internal implementation is optimized and it does not actually use call_if_c).See Also:
Assertion RequirementsParameters:else_Boolean value to return when Pred is false (instead of compiling and executing the functor template call f()).fNullary boolean functor template. The functor template call f() is compiled and executed if and only if Pred is true.Template Parameters:PredStatic boolean predicate selecting when the functor template call f() should be compiled and executed. Returns:Boolean value returned by f() if the static predicate Pred is true. Otherwise, trivially return else_. Function template condition_if3boost::contract::condition_ifSelect compilation and execution of a boolean functor template condition using a nullary boolean meta-function (not needed on C++17 compilers, use if constexpr instead). // In header: <boost/contract/call_if.hpp>
template<typename Pred,typename Then>boolcondition_if(Then f,bool else_ =true);DescriptionThis is equivalent to boost::contract::condition_if_c<Pred::value>(f, else_). Compile and execute the nullary boolean functor template call f() if and only if the specified nullary boolean meta-function Pred::value is true, otherwise trivially return else_ (true by default) at run-time.See Also:
Assertion RequirementsParameters:else_Boolean value to return when Pred::value is false (instead of compiling and executing the functor template call f()).fNullary boolean functor template. The functor template call f() is compiled and executed if and only if Pred::value is true. Template Parameters:PredNullary boolean meta-function selecting when the functor template call f() should be compiled and executed.Returns:Boolean value returned by f() if the static predicate Pred::value is true. Otherwise, trivially return else_. Header <boost/contract/check.hpp>RAII object that checks contracts. namespaceboost{namespacecontract{class check;}}Class check3boost::contract::checkRAII object that checks the contracts. // In header: <boost/contract/check.hpp>
class check {public:// construct/copy/destructtemplate<typename F>check(Fconst&);check(check const&);template<typename VirtualResult>check(specify_precondition_old_postcondition_except<VirtualResult>const&);template<typename VirtualResult>check(specify_old_postcondition_except<VirtualResult>const&);template<typename VirtualResult>check(specify_postcondition_except<VirtualResult>const&);check(specify_except const&);check(specify_nothing const&);~check();};DescriptionIn general, when this object is constructed it checks class invariants at entry, preconditions, and makes old value copies at body. When it is destructed, it checks class invariants at exist, postconditions, and exception guarantees. This object enforces the following (see Contract Programming Overview):Postconditions are checked only if the body does not throw an exception. Exceptions guarantees are checked only if the body throws an exception. Constructor entry never checks class invariants. Destructor exit checks class invariants only if the body throws an exception (even if destructors should usually not be programmed to throw exceptions in C++ and they are implicitly declared noexcept since C++11). Static invariants are always checked at entry and exit (and regardless of the body throwing exceptions or not).
When used this way, this object is constructed and initialized to the return value of one of the contract functions boost::contract::function, boost::contract::constructor, boost::contract::destructor, or boost::contract::public_function. In addition to that, this object can be constructed from a nullary functor when it is used to program implementation checks.See Also: Tutorial, Implementation Checks check
public
construct/copy/destructtemplate<typename F>check(Fconst& f);Construct this object for implementation checks. This can be used to program checks within implementation code (body, etc.). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure).Parameters:fNullary functor that asserts implementation checks. f() will be called as soon as this object is constructed at the point it is declared within the implementation code (see
Implementation Checks). check(check const& other);Construct this object copying it from the specified one. This object will check the contract, the copied-from object will not (i.e., contract check ownership is transferred from the copied object to the new object being created by this constructor).Parameters:otherCopied-from object. template<typename VirtualResult>check(specify_precondition_old_postcondition_except<VirtualResult>const& contract);Construct this object to check the specified contract. This checks class invariants at entry (if those were specified for the given contract). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure).Parameters:contractContract to be checked (usually the return value of boost::contract::function or boost::contract::public_function).Template Parameters:VirtualResultReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) template<typename VirtualResult>check(specify_old_postcondition_except<VirtualResult>const& contract);Construct this object to check the specified contract. This checks class invariants at entry and preconditions (if any of those were specified for the given contract). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure).Parameters:contractContract to be checked (usually the return value of boost::contract::function, boost::contract::constructor, boost::contract::destructor, or boost::contract::public_function).Template Parameters:VirtualResultReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) template<typename VirtualResult>check(specify_postcondition_except<VirtualResult>const& contract);Construct this object to check the specified contract. This checks class invariants at entry and preconditions then it makes old value copies at body (if any of those were specified for the given contract). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating te program (see
Throw on Failure).Parameters:contractContract to be checked (usually the return value of boost::contract::function, boost::contract::constructor, boost::contract::destructor, or boost::contract::public_function).Template Parameters:VirtualResultReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) check(specify_except const& contract);Construct this object to check the specified contract. This checks class invariants at entry and preconditions then it makes old value copies at body, plus the destructor of this object will also check postconditions in this case (if any of those were specified for the given contract). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure).Parameters:contractContract to be checked (usually the return value of boost::contract::function, boost::contract::constructor, boost::contract::destructor, or boost::contract::public_function).check(specify_nothing const& contract);Construct this object to check the specified contract. This checks class invariants at entry and preconditions then it makes old value copies at body, plus the destructor of this object will also check postconditions and exception guarantees in this case (if any of those were specified for the given contract). This constructor is not declared explicit so initializations can use assignment syntax =.Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure).Parameters:contractContract to be checked (usually the return value of boost::contract::function, boost::contract::constructor, boost::contract::destructor, or boost::contract::public_function).~check();Destruct this object. This checks class invariants at exit and either postconditions when the enclosing function body did not throw an exception, or exception guarantees when the function body threw an exception (if class invariants, postconditions, and exception guarantees respectively were specified for the enclosing class and the contract parameter given when constructing this object).Throws: This can throw in case programmers specify contract failure handlers that throw exceptions instead of terminating the program (see
Throw on Failure). (This is declared noexcept(false) since C++11.) Header <boost/contract/constructor.hpp>Program contracts for constructors. namespaceboost{namespacecontract{template<typename Class>
specify_old_postcondition_except constructor(Class*);}}Function template constructor3boost::contract::constructorProgram contracts for constructors. // In header: <boost/contract/constructor.hpp>
template<typename Class>
specify_old_postcondition_except constructor(Class* obj);DescriptionThis is used to specify postconditions, exception guarantees, old value copies at body, and check class invariants for constructors (see boost::contract::constructor_precondition to specify preconditions for constructors):classu{friendclassboost::contract:access;voidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}public:u(...){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::constructor(this)// No `.precondition` (use `constructor_precondition` instead)..old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Constructor body.}...};For optimization, this can be omitted for constructors that do not have postconditions and exception guarantees, within classes that have no invariants.See Also: ConstructorsParameters:objThe object this from the scope of the enclosing constructor declaring the contract. (Constructors check all class invariants, including static and volatile invariants, see
Class Invariants and
Volatile Public Functions).Template Parameters:ClassThe type of the class containing the constructor declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.)Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the constructor body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Header <boost/contract/core/access.hpp>Allow to declare invariants, base types, etc all as private members. namespaceboost{namespacecontract{class access;}}Class access3boost::contract::accessDeclare this class as friend to program invariants and base types as private members. // In header: <boost/contract/core/access.hpp>
class access {};DescriptionDeclare this class a friend of the user-defined class specifying the contracts and then invariant functions and the base types typedef can be declared as non-public members:classu#defineBASESpublicb,privatew:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;// Private.#undefBASESvoidinvariant()const{...}// Private (same for static and volatile).public:...};In real code, programmers will likely chose to declare this class as friend so to fully control public interfaces of their user-defined classes (this is not extensively done in the examples of this documentation only for brevity). This class is not intended to be directly used by programmers a part from being declared as friend (and that is why this class does not have any public member and it is not copyable).Not declaring this class friend of user-defined classes will cause compiler errors on some compilers (e.g., MSVC) because the private members needed to check the contracts will not be accessible. On other compilers (e.g., GCC and CLang), the private access will instead fail SFINAE and no compiler error will be reported while invariants and subcontracting will be silently skipped at run-time. Therefore, programmers must make sure to either declare this class as friend or to always declare invariant functions and base types typedef as public members.See Also: Access Specifiers Header <boost/contract/core/check_macro.hpp>Macros for implementation checks.
BOOST_CONTRACT_CHECK(cond)
BOOST_CONTRACT_CHECK_AUDIT(cond)
BOOST_CONTRACT_CHECK_AXIOM(cond)Macro BOOST_CONTRACT_CHECK3BOOST_CONTRACT_CHECKPreferred way to assert implementation check conditions. // In header: <boost/contract/core/check_macro.hpp>
BOOST_CONTRACT_CHECK(cond)DescriptionIt is preferred to use this macro instead of programming implementation checks in a nullary functor passed to boost::contract::check constructor because this macro will completely remove implementation checks from the code when BOOST_CONTRACT_NO_CHECKS is defined:voidf(){...BOOST_CONTRACT_CHECK(cond);...}BOOST_CONTRACT_CHECK, BOOST_CONTRACT_CHECK_AUDIT, and BOOST_CONTRACT_CHECK_AXIOM are the three assertion levels predefined by this library for implementation checks.See Also: Implementation ChecksParameters:condBoolean condition to check within implementation code (function body, etc.). (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_CHECK((cond)) will always work.) Macro BOOST_CONTRACT_CHECK_AUDIT3BOOST_CONTRACT_CHECK_AUDITPreferred way to assert implementation check conditions that are computationally expensive, at least compared to the computational cost of executing the function body. // In header: <boost/contract/core/check_macro.hpp>
BOOST_CONTRACT_CHECK_AUDIT(cond)DescriptionThe specified condition will always be compiled and validated syntactically, but it will not be checked at run-time unless BOOST_CONTRACT_AUDITS is defined (undefined by default). This macro is defined by code equivalent to:#ifdefBOOST_CONTRACT_AUDITS#defineBOOST_CONTRACT_CHECK_AUDIT(cond) \
BOOST_CONTRACT_CHECK(cond)#else#defineBOOST_CONTRACT_CHECK_AUDIT(cond) \
BOOST_CONTRACT_CHECK(true||cond)#endifBOOST_CONTRACT_CHECK, BOOST_CONTRACT_CHECK_AUDIT, and BOOST_CONTRACT_CHECK_AXIOM are the three assertion levels predefined by this library for implementation checks. If there is a need, programmers are free to implement their own assertion levels defining macros similar to the one above.See Also: Assertion LevelsParameters:condBoolean condition to check within implementation code (function body, etc.). (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_CHECK_AUDIT((cond)) will always work.) Macro BOOST_CONTRACT_CHECK_AXIOM3BOOST_CONTRACT_CHECK_AXIOMPreferred way to document in the code implementation check conditions that are computationally prohibitive, at least compared to the computational cost of executing the function body. // In header: <boost/contract/core/check_macro.hpp>
BOOST_CONTRACT_CHECK_AXIOM(cond)DescriptionThe specified condition will always be compiled and validated syntactically, but it will never be checked at run-time. This macro is defined by code equivalent to:#defineBOOST_CONTRACT_CHECK_AXIOM(cond) \
BOOST_CONTRACT_CHECK(true||cond)BOOST_CONTRACT_CHECK, BOOST_CONTRACT_CHECK_AUDIT, and BOOST_CONTRACT_CHECK_AXIOM are the three assertion levels predefined by this library for implementation checks. If there is a need, programmers are free to implement their own assertion levels defining macros similar to the one above.See Also: Assertion LevelsParameters:condBoolean condition to check within implementation code (function body, etc.). (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_CHECK_AXIOM((cond)) will always work.) Header <boost/contract/core/config.hpp>Configure this library compile-time and run-time behaviours.
BOOST_CONTRACT_DYN_LINK
BOOST_CONTRACT_STATIC_LINK
BOOST_CONTRACT_HEADER_ONLY
BOOST_CONTRACT_DISABLE_THREADS
BOOST_CONTRACT_MAX_ARGS
BOOST_CONTRACT_BASES_TYPEDEF
BOOST_CONTRACT_INVARIANT_FUNC
BOOST_CONTRACT_STATIC_INVARIANT_FUNC
BOOST_CONTRACT_PERMISSIVE
BOOST_CONTRACT_ON_MISSING_CHECK_DECL
BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
BOOST_CONTRACT_AUDITS
BOOST_CONTRACT_NO_CHECKS
BOOST_CONTRACT_NO_PRECONDITIONS
BOOST_CONTRACT_NO_POSTCONDITIONS
BOOST_CONTRACT_NO_EXCEPTS
BOOST_CONTRACT_NO_ENTRY_INVARIANTS
BOOST_CONTRACT_NO_EXIT_INVARIANTS
BOOST_CONTRACT_NO_INVARIANTS
BOOST_CONTRACT_NO_OLDS
BOOST_CONTRACT_NO_CONSTRUCTORS
BOOST_CONTRACT_NO_DESTRUCTORS
BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
BOOST_CONTRACT_NO_FUNCTIONS
BOOST_CONTRACT_NO_CONDITIONS
BOOST_CONTRACT_NO_ALLMacro BOOST_CONTRACT_DYN_LINK3BOOST_CONTRACT_DYN_LINKDefine this macro to compile this library as a shared library (recommended). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_DYN_LINKDescriptionIf this macro is defined, this library is compiled so it can be linked as a shared library (a.k.a., Dynamically Linked Library or DLL) to user code. This library will automatically define this macro when Boost libraries are built as shared libraries (e.g., defining BOOST_ALL_DYN_LINK or using bjam link=shared ...).In general this library will correctly check contracts at run-time only when compiled as a shared library, unless user code checks contracts in a single program unit (e.g., a single program with only statically linked libraries). Therefore, it is recommended to build and use this library as a shared library by defining this macro (or equivalently by building all Boost libraries as shared libraries).See Also: Getting Started Macro BOOST_CONTRACT_STATIC_LINK3BOOST_CONTRACT_STATIC_LINKDefine this macro to compile this library as a static library (not recommended). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_STATIC_LINKDescriptionIf this macro is defined, this library is compiled so it can be linked statically to user code. This library will automatically define this macro when Boost libraries are built as static libraries.This library is not guaranteed to always work correctly at run-time when this macro is defined (define BOOST_CONTRACT_DYN_LINK or BOOST_ALL_DYN_LINK instead). However, this macro can be defined and this library can be safely used as a static library for user code that checks contracts in a single program unit (e.g., a single program with only statically linked libraries).See Also: Getting Started Macro BOOST_CONTRACT_HEADER_ONLY3BOOST_CONTRACT_HEADER_ONLYAutomatically defined by this library when it is being used as a header-only library (not recommended). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_HEADER_ONLYDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users do not define BOOST_CONTRACT_DYN_LINK (or BOOST_ALL_DYN_LINK) and BOOST_CONTRACT_STATIC_LINK. When used as a header-only library, this library code does not have to be compiled separately from user code, this library headers are simply included and compiled as part of the user program.This library is not guaranteed to always work correctly at run-time when this macro is defined (define BOOST_CONTRACT_DYN_LINK or BOOST_ALL_DYN_LINK instead). However, this macro can be defined and this library can be safely used as a header-only library for user code that checks contracts in a single program unit (e.g., a single program with only statically linked libraries).See Also: Getting Started Macro BOOST_CONTRACT_DISABLE_THREADS3BOOST_CONTRACT_DISABLE_THREADSDefine this macro to not lock internal library data for thread safety (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_DISABLE_THREADSDescriptionDefining this macro will make the library implementation code not thread safe so this macro should not be defined unless the library is being used by single-threaded applications only. This library will automatically define this macro when Boost libraries are built without threads (e.g., defining BOOST_DISABLE_THREADS).When this macro is left undefined this library needs to internally use some sort of global lock (to ensure contract checking is globally disabled when other contracts are being checked and also to safely access failure handler functors). That could introduce an undesired amount of synchronization in some multi-threaded applications.See Also: Assertions Macro BOOST_CONTRACT_MAX_ARGS3BOOST_CONTRACT_MAX_ARGSMaximum number of arguments for public function overrides on compilers that do not support variadic templates (default to 10). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_MAX_ARGSDescriptionOn compilers that do not support C++11 variadic templates, this macro is defined to the maximum number of arguments that public function overrides can have and pass to boost::contract::public_function (users can redefine this macro to a different value). On compilers that support variadic templates, this macro has no effect.Regardless of the value of this macro and of compiler support for variadic templates, there might be an intrinsic limit of about 18 arguments for public function overrides (because of similar limits in Boost.MPL and Boost.FunctionTypes internally used by this library).See Also: No Macros Macro BOOST_CONTRACT_BASES_TYPEDEF3BOOST_CONTRACT_BASES_TYPEDEFDefine the name of the base type typedef (base_types by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_BASES_TYPEDEFDescriptionThis macro expands to the name of the typedef that lists the base classes for subcontracting via BOOST_CONTRACT_BASE_TYPES:classu#defineBASESpublicb,privatew:BASES{friendclassboost::contract:access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)BOOST_CONTRACT_TYPEDEF;#undefBASES...};When used this way, users can redefine this macro if the typedef must have a name different from base_types (because of name clashes in user code, etc.).See Also: Base Classes Macro BOOST_CONTRACT_INVARIANT_FUNC3BOOST_CONTRACT_INVARIANT_FUNCDefine the name of the class invariant member function (invariant by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_INVARIANT_FUNCDescriptionThis macro expands to the name of the const and const volatile member functions that check class invariants and volatile class invariants respectively:classu{friendclassboost::contract::access;voidBOOST_CONTRACT_INVARIANT_FUNC()const{BOOST_CONTRACT_ASSERT(...);...}voidBOOST_CONTRACT_INVARIANT_FUNC()constvolatile{BOOST_CONTRACT_ASSERT(...);...}...};When used this way, users can redefine this macro if the invariant functions must have a name different from invariant (because of name clashes in user code, etc.).C++ does not allow to overload member functions based on the static classifier, so this macro must always be defined to be different than the function name defined for BOOST_CONTRACT_STATIC_INVARIANT_FUNC.See Also: Class Invariants,
Volatile Public Functions Macro BOOST_CONTRACT_STATIC_INVARIANT_FUNC3BOOST_CONTRACT_STATIC_INVARIANT_FUNCDefine the name of the static invariant member function (static_invariant by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_STATIC_INVARIANT_FUNCDescriptionThis macro expands to the name of the static member function that checks static class invariants:classu{friendclassboost::contract::access;staticvoidBOOST_CONTRACT_STATIC_INVARIANT_FUNC(){BOOST_CONTRACT_ASSERT(...);...}...};When used this way, users can redefine this macro if the static invariant function must have a name different from static_invariant (because of name clashes in user code, etc.).C++ does not allow to overload member functions based on the static classifier, so this macro must always be defined to be different than the function name defined for BOOST_CONTRACT_INVARIANT_FUNC.See Also: Class Invariants Macro BOOST_CONTRACT_PERMISSIVE3BOOST_CONTRACT_PERMISSIVEDisable some compile-time errors generated by this library (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_PERMISSIVEDescriptionDefining this macro disables a number of static checks and related compile-time errors generated by this library, for example:The static invariant member function named as BOOST_CONTRACT_STATIC_INVARIANT_FUNC must be declared static. Non-static invariant member functions named as BOOST_CONTRACT_INVARIANT_FUNC must be declared either const, const volatile, or volatile const. Derived classes that program contracts for one or more public function overrides via boost::contract::public_function must also define the BOOST_CONTRACT_BASE_TYPEStypedef.
In general, it is not recommended to define this macro because these compile-time checks can guard against misuses of this library.See Also: Class Invariants, Base Classes Macro BOOST_CONTRACT_ON_MISSING_CHECK_DECL3BOOST_CONTRACT_ON_MISSING_CHECK_DECLCode block to execute if contracts are not assigned to a boost::contract::check variable (undefined and executes BOOST_ASSERT(false) by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_ON_MISSING_CHECK_DECLDescriptionIn general, there is a logic error in the program when contracts are not explicitly assigned to a local variable of type boost::contract::check and without using C++11 auto declarations (because that is a misuse of this library). Therefore, by default (i.e., when this macro is not defined) this library calls BOOST_ASSERT(false) in those cases. If this macro is defined, this library will execute the code expanded by this macro instead of calling BOOST_ASSERT(false) (if programmers prefer to throw an exception, etc.).This macro can also be defined to be any block of code (and use empty curly brackets {} to generate no error, not recommended), for example (on GCC): gcc-DBOOST_CONTRACT_ON_MISSING_CHECK_DECL='{ throw std::logic_error("missing contract check declaration"); }'...See Also: Tutorial Macro BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION3BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTIONDefine this macro to not disable other assertions while checking preconditions (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTIONDescriptionNot disabling other assertions while checking preconditions can lead to infinite recursion in user code so by default this macro is not defined.However, the [N1962] proposal does not disable assertions while checking preconditions because arguments can reach the function body unchecked if assertions are disabled while checking preconditions (e.g., when these same functions bodies are called to check the preconditions in question). This macro can be defined to obtain the behaviour specified in [N1962] (at the risk of infinite recursion).See Also:
Feature Summary Macro BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION3BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTIONDefine this macro to not disable any assertion while checking other assertions (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTIONDescriptionNot disabling assertions while checking other assertions can lead to infinite recursion in user code so by default this macro is not defined. (Defining this macro automatically implies that other assertion checking is disabled while checking preconditions as if BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION was also defined.)See Also:
Feature Summary Macro BOOST_CONTRACT_AUDITS3BOOST_CONTRACT_AUDITSDefine this macro to evaluate and check audit assertions at run-time (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_AUDITSDescriptionAudit assertions and implementation checks programmed via BOOST_CONTRACT_ASSERT_AUDIT and BOOST_CONTRACT_CHECK_AUDIT are always compiled and validated syntactically. However, they are not evaluated and checked at run-time unless this macro is defined (because these conditions can be computationally expensive, at least compared to the computational cost of executing the function body).See Also: Assertion Levels Macro BOOST_CONTRACT_NO_CHECKS3BOOST_CONTRACT_NO_CHECKSIf defined, this library disables implementation checks (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_CHECKSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with implementation checks. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of implementation checks or use BOOST_CONTRACT_CHECK (recommended).See Also:
Implementation Checks,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_PRECONDITIONS3BOOST_CONTRACT_NO_PRECONDITIONSIf defined, this library does not check preconditions (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_PRECONDITIONSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking preconditions. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of preconditions or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also: Preconditions,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_POSTCONDITIONS3BOOST_CONTRACT_NO_POSTCONDITIONSIf defined, this library does not check postconditions (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_POSTCONDITIONSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking postconditions. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of postconditions or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).It is necessary to disable both postconditions and exception guarantees defining BOOST_CONTRACT_NO_POSTCONDITIONS and BOOST_CONTRACT_NO_EXCEPTS in order to disable old value copies (see BOOST_CONTRACT_NO_OLDS).See Also: Postconditions,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_EXCEPTS3BOOST_CONTRACT_NO_EXCEPTSIf defined, this library does not check exception guarantees (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_EXCEPTSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking exception guarantees. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of exception guarantees or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).It is necessary to disable both postconditions and exception guarantees defining BOOST_CONTRACT_NO_POSTCONDITIONS and BOOST_CONTRACT_NO_EXCEPTS in order to disable old value copies (see BOOST_CONTRACT_NO_OLDS).See Also: Exception Guarantees,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_ENTRY_INVARIANTS3BOOST_CONTRACT_NO_ENTRY_INVARIANTSIf defined, this library does not check class invariants at entry (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_ENTRY_INVARIANTSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking class invariants at entry. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of entry class invariants or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).This macro is automatically defined when BOOST_CONTRACT_NO_INVARIANTS is defined.See Also: Class Invariants,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS3BOOST_CONTRACT_NO_EXIT_INVARIANTSIf defined, this library does not check class invariants at exit (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_EXIT_INVARIANTSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking class invariants at exit. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of exit class invariants or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).This macro is automatically defined when BOOST_CONTRACT_NO_INVARIANTS is defined.See Also: Class Invariants,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_INVARIANTS3BOOST_CONTRACT_NO_INVARIANTSIf defined, this library does not check class invariants (undefined by default). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_INVARIANTSDescriptionIf this macro is defined, this library internal code is also optimized to reduce compile-time (not just run-time) overhead associated with checking class invariants. In addition, users can manually program #ifndef statements in their code using this macro to completely disable compilation of class invariants or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).Defining this macro is equivalent to defining both BOOST_CONTRACT_NO_ENTRY_INVARIANTS and BOOST_CONTRACT_NO_EXIT_INVARIANTS.See Also: Class Invariants,
Disable Contract Checking,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_OLDS3BOOST_CONTRACT_NO_OLDSAutomatically defined by this library when old value copies are not to be performed. // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_OLDSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define both BOOST_CONTRACT_NO_POSTCONDITIONS and BOOST_CONTRACT_NO_EXCEPTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of old value copies or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also: Old Values,
Old Values Copied at Body,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_CONSTRUCTORS3BOOST_CONTRACT_NO_CONSTRUCTORSAutomatically defined by this library when contracts are not checked for constructors. // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_CONSTRUCTORSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_INVARIANTS, BOOST_CONTRACT_NO_POSTCONDITIONS, and BOOST_CONTRACT_NO_EXCEPTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of contracts for constructors or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).Constructor preconditions are checked separately by boost::contract::constructor_precondition so they are disabled by BOOST_CONTRACT_NO_PRECONDITIONS instead.See Also: Constructors,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_DESTRUCTORS3BOOST_CONTRACT_NO_DESTRUCTORSAutomatically defined by this library when contracts are not checked for destructors. // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_DESTRUCTORSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_INVARIANTS, BOOST_CONTRACT_NO_POSTCONDITIONS, and BOOST_CONTRACT_NO_EXCEPTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of contracts for destructors or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also: Destructors,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS3BOOST_CONTRACT_NO_PUBLIC_FUNCTIONSAutomatically defined by this library when contracts are not checked for public functions. // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_PUBLIC_FUNCTIONSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_INVARIANTS, BOOST_CONTRACT_NO_PRECONDITIONS, BOOST_CONTRACT_NO_POSTCONDITIONS, and BOOST_CONTRACT_NO_EXCEPTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of contracts for public functions or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also: Public Functions,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_FUNCTIONS3BOOST_CONTRACT_NO_FUNCTIONSAutomatically defined by this library when contracts are not checked for non-member, private, or protected functions. // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_FUNCTIONSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_PRECONDITIONS, BOOST_CONTRACT_NO_POSTCONDITIONS, and BOOST_CONTRACT_NO_EXCEPTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of contracts for non-member, private and protected functions, or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).This macro is also used when contracts are not checked for private or protected functions, lambda functions, code blocks, loops, etc.See Also: Non-Member Functions,
Private and Protected Functions,
Lambdas, Loops, Code Blocks,
Disable Contract Compilation Macro BOOST_CONTRACT_NO_CONDITIONS3BOOST_CONTRACT_NO_CONDITIONSAutomatically defined by this library when contracts are not checked for preconditions, postconditions, exceptions guarantees, and class invariants (excluding implementation checks). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_CONDITIONSDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_PRECONDITIONS, BOOST_CONTRACT_NO_POSTCONDITIONS, BOOST_CONTRACT_NO_EXCEPTS, and BOOST_CONTRACT_NO_INVARIANTS. Users can manually program #ifndef statements in their code using this macro to completely disable compilation of contracts within specifications (so excluding implementation checks which are contracts within implementations instead), or use the macros defined in boost/contract_macro.hpp (recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also:
Disable Contract Compilation Macro BOOST_CONTRACT_NO_ALL3BOOST_CONTRACT_NO_ALLAutomatically defined by this library when contracts are not checked at all (neither for specifications nor for implementations). // In header: <boost/contract/core/config.hpp>
BOOST_CONTRACT_NO_ALLDescriptionThis macro is not a configuration macro and this library will generate a compile-time error if users try to define it directly. This library will automatically define this macro when users define all BOOST_CONTRACT_NO_INVARIANTS, BOOST_CONTRACT_NO_PRECONDITIONS, BOOST_CONTRACT_NO_POSTCONDITIONS, BOOST_CONTRACT_NO_EXCEPTS, and BOOST_CONTRACT_NO_CHECKS. For example, users can manually program #ifndef statements in their code using this macro to avoid including the boost/contract.hpp header all together:#include<boost/contract/core/config.hpp>#ifndefBOOST_CONTRACT_NO_ALL#include<boost/contract.hpp>#endifOr, use the boost/contract_macro.hpp header and related macros instead (because the boost/contract_macro.hpp header is already optimized to not include other headers from this library when contracts are not checked, but recommended only for applications where it is truly necessary to completely remove contract code compilation from production code).See Also:
Disable Contract Compilation Header <boost/contract/core/constructor_precondition.hpp>Program preconditions for constructors. namespaceboost{namespacecontract{template<typename Class>class constructor_precondition;}}Class template constructor_precondition3boost::contract::constructor_preconditionProgram preconditions for constructors. // In header: <boost/contract/core/constructor_precondition.hpp>
template<typename Class>class constructor_precondition {public:// construct/copy/destructconstructor_precondition();template<typename F>explicitconstructor_precondition(Fconst&);};DescriptionThis class must be the very first base of the class declaring the constructor for which preconditions are programmed (that way constructor arguments can be checked by preconditions even before they are used to initialize other base classes):classu#defineBASESprivateboost::contract::constructor_precondition<u>, \
publicb:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESpublic:explicitu(unsignedx):boost::contract::constructor_precondition<u>([&]{BOOST_CONTRACT_ASSERT(x!=0);...}),b(1.0/float(x)){...}...};User-defined classes should inherit privately from this class (to not alter the public interface of user-defined classes). In addition, this class should never be declared as a virtual base (because virtual bases are initialized only once across the entire inheritance hierarchy preventing preconditions of other base classes from being checked).This class cannot be used this way in a union because unions cannot have base classes in C++. Instead, this class is used in a union to declare a local object within the constructor definition just before boost::contract::constructor is used (see Unions).See Also: ConstructorsTemplate Parameterstypename ClassThe class type of the constructor for which preconditions are being programmed. constructor_precondition
public
construct/copy/destructconstructor_precondition();Construct this object without specifying constructor preconditions. This is implicitly called for those constructors of the contracted class that do not specify preconditions.The implementation of this library is optimized so that calling this default constructor should amount to negligible compile-time and run-time overheads (likely to be optimized away completely by most compilers). template<typename F>explicitconstructor_precondition(Fconst& f);Construct this object specifying constructor preconditions. Parameters:fNullary functor called by this library to check constructor preconditions f(). Assertions within this functor call are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract failure (and will result in this library calling boost::contract::precondition_failure). This functor should capture variables by (constant) value, or better by (constant) reference to avoid extra copies. Header <boost/contract/core/exception.hpp>Handle contract assertion failures. namespaceboost{namespacecontract{class assertion_failure;class bad_virtual_result_cast;class exception;enum from;typedefboost::function<void(from)>from_failure_handler;typedefboost::function<void()>failure_handler;failure_handlerconst&set_check_failure(failure_handlerconst&);failure_handlerget_check_failure();voidcheck_failure();from_failure_handlerconst&set_precondition_failure(from_failure_handlerconst&);from_failure_handlerget_precondition_failure();voidprecondition_failure(from);from_failure_handlerconst&set_postcondition_failure(from_failure_handlerconst&);from_failure_handlerget_postcondition_failure();voidpostcondition_failure(from);from_failure_handlerconst&set_except_failure(from_failure_handlerconst&);from_failure_handlerget_except_failure();voidexcept_failure(from);from_failure_handlerconst&set_old_failure(from_failure_handlerconst&);from_failure_handlerget_old_failure();voidold_failure(from);from_failure_handlerconst&set_entry_invariant_failure(from_failure_handlerconst&);from_failure_handlerget_entry_invariant_failure();voidentry_invariant_failure(from);from_failure_handlerconst&set_exit_invariant_failure(from_failure_handlerconst&);from_failure_handlerget_exit_invariant_failure();voidexit_invariant_failure(from);from_failure_handlerconst&set_invariant_failure(from_failure_handlerconst&);}}Class assertion_failure3boost::contract::assertion_failureException typically used to report a contract assertion failure. // In header: <boost/contract/core/exception.hpp>
class assertion_failure :publicstd::exception, publicboost::contract::exception{public:// construct/copy/destructexplicitassertion_failure(charconst*="",unsignedlong=0,charconst*="");explicitassertion_failure(charconst*);~assertion_failure();// public member functionsvirtualcharconst*what()const;charconst*file()const;unsignedlongline()const;charconst*code()const;};DescriptionThis exception is thrown by code expanded by BOOST_CONTRACT_ASSERT (but it can also be thrown by user code programmed manually without that macro). This exception is typically used to report contract assertion failures because it contains detailed information about the file name, line number, and source code of the asserted condition (so it can be used by this library to provide detailed error messages when handling contract assertion failures).However, any other exception can be used to report a contract assertion failure (including user-defined exceptions). This library will call the appropriate contract failure handler function ( boost::contract::precondition_failure, etc.) when this or any other exception is thrown while checking contracts (by default, these failure handler functions print an error message to std::cerr and terminate the program, but they can be customized to take any other action).See Also: Throw on Failure, No Macros assertion_failure
public
construct/copy/destructexplicitassertion_failure(charconst* file ="",unsignedlong line =0,charconst* code ="");Construct this object with file name, line number, and source code text of an assertion condition (all optional). This constructor can also be used to specify no information (default constructor), or to specify only file name and line number but not source code text (because of the parameter default values).Parameters:codeText listing the source code of the assertion condition. fileName of the file containing the assertion (usually set using __FILE__). lineNumber of the line containing the assertion (usually set using __LINE__). explicitassertion_failure(charconst* code);Construct this object only with the source code text of the assertion condition. Parameters:codeText listing the source code of the assertion condition. ~assertion_failure();Destruct this object. Throws: This is declared noexcept (or throw() before C++11). assertion_failure public member functionsvirtualcharconst*what()const;String describing the failed assertion. Throws: This is declared noexcept (or throw() before C++11).Returns:A string formatted similarly to the following: assertion "`code()`" failed: file "`file()`", line `line()` (where `` indicate execution quotes). File, line, and code will be omitted from this string if they were not specified when constructing this object. charconst*file()const;Name of the file containing the assertion. Returns:File name as specified at construction (or "" if no file was specified). unsignedlongline()const;Number of the line containing the assertion. Returns:Line number as specified at construction (or 0 if no line number was specified). charconst*code()const;Text listing the source code of the assertion condition. Returns:Assertion condition source code as specified at construction (or "" if no source code text was specified). Class bad_virtual_result_cast3boost::contract::bad_virtual_result_castException thrown when inconsistent return values are passed to overridden virtual public functions. // In header: <boost/contract/core/exception.hpp>
class bad_virtual_result_cast :publicstd::bad_cast, publicboost::contract::exception{public:// construct/copy/destructexplicitbad_virtual_result_cast(charconst*,charconst*);~bad_virtual_result_cast();// public member functionsvirtualcharconst*what()const;};DescriptionThis exception is thrown when programmers pass to this library return value parameters for public function overrides in derived classes that are not consistent with the return type parameter passed for the virtual public function being overridden from the base classes. This allows this library to give more descriptive error messages in such cases of misuse.This exception is internally thrown by this library and programmers should not need to throw it from user code.See Also:
Public Function Overrides bad_virtual_result_cast
public
construct/copy/destructexplicitbad_virtual_result_cast(charconst* from_type_name,charconst* to_type_name);Construct this object with the name of the from- and to- result types. Parameters:from_type_nameName of the from-type (source of the cast). to_type_nameName of the to-type (destination of the cast). ~bad_virtual_result_cast();Destruct this object. Throws: This is declared noexcept (or throw() before C++11). bad_virtual_result_cast public member functionsvirtualcharconst*what()const;Description for this error (containing both from- and to- type names). Throws: This is declared noexcept (or throw() before C++11). Class exception3boost::contract::exceptionPublic base class for all exceptions directly thrown by this library. // In header: <boost/contract/core/exception.hpp>
class exception {public:// construct/copy/destruct~exception();};DescriptionThis class does not inherit from std::exception because exceptions deriving from this class will do that (inheriting from std::exception, std::bad_cast, etc.).See Also:boost::contract::assertion_failure, boost::contract::bad_virtual_result_cast, etc. exception
public
construct/copy/destruct~exception();Destruct this object. Throws: This is declared noexcept (or throw() before C++11). Type from3boost::contract::fromIndicate the kind of operation where the contract assertion failed. // In header: <boost/contract/core/exception.hpp>
enumfrom{ from_constructor, from_destructor, from_function };DescriptionThis is passed as a parameter to the assertion failure handler functions. For example, it might be necessary to know in which operation an assertion failed to make sure exceptions are never thrown from destructors, not even when contract failure handlers are programmed by users to throw exceptions instead of terminating the program.See Also: Throw on Failure from_constructorAssertion failed when checking contracts for constructors. from_destructorAssertion failed when checking contracts for destructors . from_functionAssertion failed when checking contracts for functions (members or not, public or not). Type definition from_failure_handler3from_failure_handlerType of assertion failure handler functions (with from parameter). // In header: <boost/contract/core/exception.hpp>
typedefboost::function<void(from)>from_failure_handler;DescriptionAssertion failure handler functions specified by this type must be functors returning void and taking a single parameter of type boost::contract::from. For example, this is used to specify contract failure handlers for class invariants, preconditions, postconditions, and exception guarantees.See Also: Throw on Failure Type definition failure_handler3failure_handlerType of assertion failure handler functions (without from parameter). // In header: <boost/contract/core/exception.hpp>
typedefboost::function<void()>failure_handler;DescriptionAssertion failure handler functions specified by this type must be nullary functors returning void. For example, this is used to specify contract failure handlers for implementation checks.See Also: Throw on Failure Function set_check_failure3boost::contract::set_check_failureSet failure handler for implementation checks. // In header: <boost/contract/core/exception.hpp>
failure_handlerconst&set_check_failure(failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Implementation Checks Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_check_failure3boost::contract::get_check_failureReturn failure handler currently set for implementation checks. // In header: <boost/contract/core/exception.hpp>
failure_handlerget_check_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Implementation Checks Returns:A copy of the failure handler currently set.Function check_failure3boost::contract::check_failureCall failure handler for implementation checks. // In header: <boost/contract/core/exception.hpp>
voidcheck_failure();DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on implementation check failures (not the default).See Also: Throw on Failure, Implementation Checks Function set_precondition_failure3boost::contract::set_precondition_failureSet failure handler for preconditions. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_precondition_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Preconditions Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_precondition_failure3boost::contract::get_precondition_failureReturn failure handler currently set for preconditions. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_precondition_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Preconditions Returns:A copy of the failure handler currently set.Function precondition_failure3boost::contract::precondition_failureCall failure handler for preconditions. // In header: <boost/contract/core/exception.hpp>
voidprecondition_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default).See Also: Throw on Failure, Preconditions Parameters:whereOperation that failed the contract assertion (when this function is called by this library, this parameter will never be from_destructor because destructors do not have preconditions).Function set_postcondition_failure3boost::contract::set_postcondition_failureSet failure handler for postconditions. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_postcondition_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Postconditions Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_postcondition_failure3boost::contract::get_postcondition_failureReturn failure handler currently set for postconditions. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_postcondition_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Postconditions Returns:A copy of the failure handler currently set.Function postcondition_failure3boost::contract::postcondition_failureCall failure handler for postconditions. // In header: <boost/contract/core/exception.hpp>
voidpostcondition_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default).See Also: Throw on Failure, Postconditions Parameters:whereOperation that failed the contract assertion (e.g., this might be useful to program failure handler functors that never throw from destructors, not even when they are programmed by users to throw exceptions instead of terminating the program).Function set_except_failure3boost::contract::set_except_failureSet failure handler for exception guarantees. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_except_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Exception Guarantees Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_except_failure3boost::contract::get_except_failureReturn failure handler currently set for exception guarantees. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_except_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Exception Guarantees Returns:A copy of the failure handler currently set.Function except_failure3boost::contract::except_failureCall failure handler for exception guarantees. // In header: <boost/contract/core/exception.hpp>
voidexcept_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default), however:When this failure handler is called there is already an active exception (the one that caused the exception guarantees to be checked in the first place). Therefore, programming this failure handler to throw yet another exception will force C++ to automatically terminate the program.See Also: Throw on Failure, Exception Guarantees Parameters:whereOperation that failed the contract assertion.Function set_old_failure3boost::contract::set_old_failureSet failure handler for old values copied at body. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_old_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Old Values Copied at Body Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_old_failure3boost::contract::get_old_failureReturn failure handler currently set for old values copied at body. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_old_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Old Values Copied at Body Returns:A copy of the failure handler currently set.Function old_failure3boost::contract::old_failureCall failure handler for old values copied at body. // In header: <boost/contract/core/exception.hpp>
voidold_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default).See Also: Throw on Failure, Old Values Copied at Body Parameters:whereOperation that failed the old value copy (e.g., this might be useful to program failure handler functors that never throw from destructors, not even when they are programmed by users to throw exceptions instead of terminating the program).Function set_entry_invariant_failure3boost::contract::set_entry_invariant_failureSet failure handler for class invariants at entry. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_entry_invariant_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_entry_invariant_failure3boost::contract::get_entry_invariant_failureReturn failure handler currently set for class invariants at entry. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_entry_invariant_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Returns:A copy of the failure handler currently set.Function entry_invariant_failure3boost::contract::entry_invariant_failureCall failure handler for class invariants at entry. // In header: <boost/contract/core/exception.hpp>
voidentry_invariant_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Parameters:whereOperation that failed the contract assertion (e.g., this might be useful to program failure handler functors that never throw from destructors, not even when they are programmed by users to throw exceptions instead of terminating the program).Function set_exit_invariant_failure3boost::contract::set_exit_invariant_failureSet failure handler for class invariants at exit. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_exit_invariant_failure(from_failure_handlerconst& f);DescriptionSet a new failure handler and returns it.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Parameters:fNew failure handler functor to set.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Function get_exit_invariant_failure3boost::contract::get_exit_invariant_failureReturn failure handler currently set for class invariants at exit. // In header: <boost/contract/core/exception.hpp>
from_failure_handlerget_exit_invariant_failure();DescriptionThis is often called only internally by this library.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Returns:A copy of the failure handler currently set.Function exit_invariant_failure3boost::contract::exit_invariant_failureCall failure handler for class invariants at exit. // In header: <boost/contract/core/exception.hpp>
voidexit_invariant_failure(from where);DescriptionThis is often called only internally by this library.Throws: This can throw in case programmers specify a failure handler that throws exceptions on contract assertion failures (not the default).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Parameters:whereOperation that failed the contract assertion (e.g., this might be useful to program failure handler functors that never throw from destructors, not even when they are programmed by users to throw exceptions instead of terminating the program).Function set_invariant_failure3boost::contract::set_invariant_failureSet failure handler for class invariants (at both entry and exit). // In header: <boost/contract/core/exception.hpp>
from_failure_handlerconst&set_invariant_failure(from_failure_handlerconst& f);DescriptionThis is provided for convenience and it is equivalent to call both boost::contract::set_entry_invariant_failure and boost::contract::set_exit_invariant_failure with the same functor parameter f.Throws: This is declared noexcept (or throw() before C++11).See Also: Throw on Failure, Class Invariants,
Volatile Public Functions Parameters:fNew failure handler functor to set for both entry and exit invariants.Returns:Same failure handler functor f passed as parameter (e.g., for concatenating function calls).Header <boost/contract/core/specify.hpp>Specify preconditions, old values copied at body, postconditions, and exception guarantees. Preconditions, old values copied at body, postconditions, and exception guarantees are all optionals but, when they are specified, they need to be specified in that order. namespaceboost{namespacecontract{class specify_except;class specify_nothing;template<typename VirtualResult =void>class specify_old_postcondition_except;template<typename VirtualResult =void>class specify_postcondition_except;template<typename VirtualResult =void>class specify_precondition_old_postcondition_except;}}Class specify_except3boost::contract::specify_exceptAllow to specify exception guarantees. // In header: <boost/contract/core/specify.hpp>
class specify_except {public:// construct/copy/destruct~specify_except();// public member functionstemplate<typename F> specify_nothing except(Fconst&);};DescriptionAllow to specify the functor this library will call to check exception guarantees. This object is internally constructed by the library when users specify contracts calling boost::contract::function and similar functions (that is why this class does not have a public constructor).See Also: Exception Guarantees specify_except
public
construct/copy/destruct~specify_except();Destruct this object. Throws: This is declared noexcept(false) since C++11 to allow users to program failure handlers that throw exceptions on contract assertion failures (not the default, see
Throw on Failure). specify_except public member functionstemplate<typename F> specify_nothing except(Fconst& f);Allow to specify exception guarantees. Parameters:fNullary functor called by this library to check exception guarantees f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::except_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit).Returns:After exception guarantees have been specified, the object returned by this function does not allow to specify any additional contract. Class specify_nothing3boost::contract::specify_nothingUsed to prevent setting other contract conditions after exception guarantees. // In header: <boost/contract/core/specify.hpp>
class specify_nothing {public:// construct/copy/destruct~specify_nothing();};DescriptionThis class has no member function so it is used to prevent specifying additional functors to check any other contract. This object is internally constructed by the library when users specify contracts calling boost::contract::function and similar functions (that is why this class does not have a public constructor).See Also: Tutorial specify_nothing
public
construct/copy/destruct~specify_nothing();Destruct this object. Throws: This is declared noexcept(false) since C++11 to allow users to program failure handlers that throw exceptions on contract assertion failures (not the default, see
Throw on Failure). Class template specify_old_postcondition_except3boost::contract::specify_old_postcondition_exceptAllow to specify old values copied at body, postconditions, and exception guarantees. // In header: <boost/contract/core/specify.hpp>
template<typename VirtualResult =void>class specify_old_postcondition_except {public:// construct/copy/destruct~specify_old_postcondition_except();// public member functionstemplate<typename F>
specify_postcondition_except<VirtualResult>old(Fconst&);template<typename F> specify_except postcondition(Fconst&);template<typename F> specify_nothing except(Fconst&);};DescriptionAllow to specify functors this library will call to copy old values at body, check postconditions, and check exception guarantees. This object is internally constructed by the library when users specify contracts calling boost::contract::function and similar functions (that is why this class does not have a public constructor).See Also: Old Values Copied at Body, Postconditions, Exception GuaranteesTemplate Parameterstypename VirtualResult =voidReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) specify_old_postcondition_except
public
construct/copy/destruct~specify_old_postcondition_except();Destruct this object. Throws: This is declared noexcept(false) since C++11 to allow users to program failure handlers that throw exceptions on contract assertion failures (not the default, see
Throw on Failure). specify_old_postcondition_except public member functionstemplate<typename F>
specify_postcondition_except<VirtualResult>old(Fconst& f);Allow to specify old values copied at body. It should often be sufficient to initialize old value pointers as soon as they are declared, without using this function (see Old Values Copied at Body).Parameters:fNullary functor called by this library f() to assign old value copies just before the body is executed but after entry invariants (when they apply) and preconditions are checked. Old value pointers within this functor call are usually assigned using BOOST_CONTRACT_OLDOF. Any exception thrown by a call to this functor will result in this library calling boost::contract::old_failure (because old values could not be copied to check postconditions and exception guarantees). This functor should capture old value pointers by references so they can be assigned (all other variables needed to evaluate old value expressions can be captured by (constant) value, or better by (constant) reference to avoid extra copies).Returns:After old values copied at body have been specified, the object returned by this function allows to optionally specify postconditions and exception guarantees. template<typename F> specify_except postcondition(Fconst& f);Allow to specify postconditions. Parameters:fFunctor called by this library to check postconditions f() or f(result). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::postcondition_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit). This functor must be a nullary functor f() if VirtualResult is void, otherwise it must be a unary functor f(result) accepting the return value result as a parameter of type VirtualResult const& (to avoid extra copies of the return value, or of type VirtualResult or VirtualResult const if extra copies of the return value are irrelevant).Returns:After postconditions have been specified, the object returned by this function allows to optionally specify exception guarantees. template<typename F> specify_nothing except(Fconst& f);Allow to specify exception guarantees. Parameters:fNullary functor called by this library to check exception guarantees f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::except_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit).Returns:After exception guarantees have been specified, the object returned by this function does not allow to specify any additional contract. Class template specify_postcondition_except3boost::contract::specify_postcondition_exceptAllow to specify postconditions or exception guarantees. // In header: <boost/contract/core/specify.hpp>
template<typename VirtualResult =void>class specify_postcondition_except {public:// construct/copy/destruct~specify_postcondition_except();// public member functionstemplate<typename F> specify_except postcondition(Fconst&);template<typename F> specify_nothing except(Fconst&);};DescriptionAllow to specify functors this library will call to check postconditions or exception guarantees. This object is internally constructed by the library when users specify contracts calling boost::contract::function and similar functions (that is why this class does not have a public constructor).See Also: Postconditions, Exception GuaranteesTemplate Parameterstypename VirtualResult =voidReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) specify_postcondition_except
public
construct/copy/destruct~specify_postcondition_except();Destruct this object. Throws: This is declared noexcept(false) since C++11 to allow users to program failure handlers that throw exceptions on contract assertion failures (not the default, see
Throw on Failure). specify_postcondition_except public member functionstemplate<typename F> specify_except postcondition(Fconst& f);Allow to specify postconditions. Parameters:fFunctor called by this library to check postconditions f() or f(result). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::postcondition_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit). This functor must be a nullary functor f() if VirtualResult is void, otherwise it must be a unary functor f(result) accepting the return value result as a parameter of type VirtualResult const& (to avoid extra copies of the return value, or of type VirtualResult or VirtualResult const if extra copies of the return value are irrelevant).Returns:After postconditions have been specified, the object returned by this function allows to optionally specify exception guarantees. template<typename F> specify_nothing except(Fconst& f);Allow to specify exception guarantees. Parameters:fNullary functor called by this library to check exception guarantees f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::except_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit).Returns:After exception guarantees have been specified, the object returned by this function does not allow to specify any additional contract. Class template specify_precondition_old_postcondition_except3boost::contract::specify_precondition_old_postcondition_exceptAllow to specify preconditions, old values copied at body, postconditions, and exception guarantees. // In header: <boost/contract/core/specify.hpp>
template<typename VirtualResult =void>class specify_precondition_old_postcondition_except {public:// construct/copy/destruct~specify_precondition_old_postcondition_except();// public member functionstemplate<typename F>
specify_old_postcondition_except<VirtualResult>precondition(Fconst&);template<typename F>
specify_postcondition_except<VirtualResult>old(Fconst&);template<typename F> specify_except postcondition(Fconst&);template<typename F> specify_nothing except(Fconst&);};DescriptionAllow to specify functors this library will call to check preconditions, copy old values at body, check postconditions, and check exception guarantees. This object is internally constructed by the library when users specify contracts calling boost::contract::function and similar functions (that is why this class does not have a public constructor).See Also: Preconditions, Old Values Copied at Body, Postconditions, Exception GuaranteesTemplate Parameterstypename VirtualResult =voidReturn type of the enclosing function declaring the contract if that is either a virtual or an overriding public function, otherwise this is always void. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) specify_precondition_old_postcondition_except
public
construct/copy/destruct~specify_precondition_old_postcondition_except();Destruct this object. Throws: This is declared noexcept(false) since C++11 to allow users to program failure handlers that throw exceptions on contract assertion failures (not the default, see
Throw on Failure). specify_precondition_old_postcondition_except public member functionstemplate<typename F>
specify_old_postcondition_except<VirtualResult>precondition(Fconst& f);Allow to specify preconditions. Parameters:fNullary functor called by this library to check preconditions f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::precondition_failure). This functor should capture variables by (constant) value, or better by (constant) reference (to avoid extra copies).Returns:After preconditions have been specified, the object returned by this function allows to optionally specify old values copied at body, postconditions, and exception guarantees. template<typename F>
specify_postcondition_except<VirtualResult>old(Fconst& f);Allow to specify old values copied at body. It should often be sufficient to initialize old value pointers as soon as they are declared, without using this function (see Old Values Copied at Body).Parameters:fNullary functor called by this library f() to assign old value copies just before the body is executed but after entry invariants (when they apply) and preconditions are checked. Old value pointers within this functor call are usually assigned using BOOST_CONTRACT_OLDOF. Any exception thrown by a call to this functor will result in this library calling boost::contract::old_failure (because old values could not be copied to check postconditions and exception guarantees). This functor should capture old value pointers by references so they can be assigned (all other variables needed to evaluate old value expressions can be captured by (constant) value, or better by (constant) reference to avoid extra copies).Returns:After old values copied at body have been specified, the object returned by this functions allows to optionally specify postconditions and exception guarantees. template<typename F> specify_except postcondition(Fconst& f);Allow to specify postconditions. Parameters:fFunctor called by this library to check postconditions f() or f(result). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::postcondition_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit). This functor must be a nullary functor f() if VirtualResult is void, otherwise it must be a unary functor f(result) accepting the return value result as a parameter of type VirtualResult const& (to avoid extra copies of the return value, or of type VirtualResult or VirtualResult const if extra copies of the return value are irrelevant).Returns:After postconditions have been specified, the object returned by this function allows to optionally specify exception guarantees. template<typename F> specify_nothing except(Fconst& f);Allow to specify exception guarantees. Parameters:fNullary functor called by this library to check exception guarantees f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::except_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit).Returns:After exception guarantees have been specified, the object returned by this function does not allow to specify any additional contract. Header <boost/contract/core/virtual.hpp>Handle virtual public functions with contracts (for subcontracting). namespaceboost{namespacecontract{class virtual_;}}Class virtual_3boost::contract::virtual_Type of extra function parameter to handle contracts for virtual public functions (for subcontracting). // In header: <boost/contract/core/virtual.hpp>
class virtual_ {};DescriptionVirtual public functions (and therefore also public function overrides) declaring contracts using this library must specify an extra function parameter at the very end of their parameter list. This parameter must be a pointer to this class and it must have default value 0 or nullptr (this extra parameter is often named v in this documentation, but any name can be used):classu{public:virtualvoidf(intx,boost::contract::virtual_*v=0){// Declare `v`....// Contract declaration (which will use `v`) and function body.}...};In practice this extra parameter does not alter the calling interface of the enclosing function declaring the contract because it is always the very last parameter and it has a default value (so it can always be omitted when users call the function). This extra parameter must be passed to boost::contract::public_function, BOOST_CONTRACT_OLDOF, and all other operations of this library that accept a pointer to boost::contract::virtual_. A part from that, this class is not intended to be directly used by programmers (and that is why this class does not have any public member and it is not copyable).See Also: Virtual Public Functions,
Public Function Overrides Header <boost/contract/destructor.hpp>Program contracts for destructors. namespaceboost{namespacecontract{template<typename Class>
specify_old_postcondition_except destructor(Class*);}}Function template destructor3boost::contract::destructorProgram contracts for destructors. // In header: <boost/contract/destructor.hpp>
template<typename Class>
specify_old_postcondition_except destructor(Class* obj);DescriptionThis is used to specify postconditions, exception guarantees, old value copies at body, and check class invariants for destructors (destructors cannot have preconditions, see Destructor Calls):classu{friendclassboost::contract::access;voidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}public:~u(){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::destructor(this)// No `.precondition` (destructors have no preconditions)..old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Destructor body.}...};For optimization, this can be omitted for destructors that do not have postconditions and exception guarantees, within classes that have no invariants.See Also: DestructorsParameters:objThe object this from the scope of the enclosing destructor declaring the contract. (Destructors check all class invariants, including static and volatile invariants, see
Class Invariants and
Volatile Public Functions).Template Parameters:ClassThe type of the class containing the destructor declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.)Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the destructor body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Header <boost/contract/function.hpp>Program contracts for (non-public) functions. namespaceboost{namespacecontract{
specify_precondition_old_postcondition_except function();}}Function function3boost::contract::functionProgram contracts for non-member, private and protected functions. // In header: <boost/contract/function.hpp>
specify_precondition_old_postcondition_except function();DescriptionThis is used to specify preconditions, postconditions, exception guarantees, and old value copies at body for non-member, private and protected functions (these functions never check class invariants, see Function Calls):voidf(...){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::function().precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body.}This can be used also to program contracts in implementation code for lambda functions, loops, and arbitrary blocks of code. For optimization, this can be omitted for code that does not have preconditions, postconditions, and exception guarantees.See Also: Non-Member Functions,
Private and Protected Functions,
Lambdas, Loops, Code BlocksReturns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Header <boost/contract/old.hpp>Handle old values.
BOOST_CONTRACT_OLDOF(...)namespaceboost{namespacecontract{template<typename T>struct is_old_value_copyable;class old_pointer;template<typename T>class old_ptr;template<typename T>class old_ptr_if_copyable;class old_value;template<typename T>struct old_value_copy;
old_value null_old();
old_pointer make_old(old_value const&);
old_pointer make_old(virtual_ *, old_value const&);boolcopy_old();boolcopy_old(virtual_ *);}}Struct template is_old_value_copyable3boost::contract::is_old_value_copyableTrait to check if an old value type can be copied or not. // In header: <boost/contract/old.hpp>
template<typename T>struct is_old_value_copyable :publicboost::is_copy_constructible<T>{};DescriptionBy default, this unary boolean meta-function is equivalent to boost::is_copy_constructible<T> but programmers can chose to specialize it for user-defined types (in general some kind of specialization is also needed on compilers that do not support C++11, see boost::is_copy_constructible):classu;// Some user-defined type for which old values shall not be copied.namespaceboost{namespacecontract{template<>// Specialization to not copy old values of type `u`.structis_old_value_copyable<u>:boost::false_type{};}}// namespaceA given old value type T is copied only if boost::contract::is_old_value_copyable<T>::value is true. A copyable old value type V is always copied using boost::contract::old_value_copy<V>. A non-copyable old value type W generates a compile-time error when boost::contract::old_ptr<W> is dereferenced, but instead leaves boost::contract::old_ptr_if_copyable<W> always null (without generating compile-time errors).See Also:
Old Value Requirements Class old_pointer3boost::contract::old_pointerConvert old value copies into old value pointers. // In header: <boost/contract/old.hpp>
class old_pointer {public:// public member functionstemplate<typename T>operatorold_ptr_if_copyable<T>();template<typename T>operatorold_ptr<T>();};DescriptionThis class is usually only implicitly used by this library and it does not explicitly appear in user code (that is why this class does not have public constructors, etc.). old_pointer public member functionstemplate<typename T>operatorold_ptr_if_copyable<T>();Convert this object to an actual old value pointer for which the old value type T might or not be copyable. For example, this is implicitly called when assigning or initializing old value pointers of type boost::contract::old_ptr_if_copyable.Template Parameters:TType of the pointed old value. The old value pointer will always be null if this type is not copyable (see boost::contract::is_old_value_copyable), but this library will not generate a compile-time error. template<typename T>operatorold_ptr<T>();Convert this object to an actual old value pointer for which the old value type T must be copyable. For example, this is implicitly called when assigning or initializing old value pointers of type boost::contract::old_ptr.Template Parameters:TType of the pointed old value. This type must be copyable (see boost::contract::is_old_value_copyable), otherwise this library will generate a compile-time error when the old value pointer is dereferenced. Class template old_ptr3boost::contract::old_ptrOld value pointer that requires the pointed old value type to be copyable. // In header: <boost/contract/old.hpp>
template<typename T>class old_ptr {public:// typestypedefTelement_type;// Pointed old value type. // construct/copy/destructold_ptr();// public member functionsTconst&operator*()const;Tconst*operator->()const;explicitoperatorbool()const;};DescriptionThis pointer can be set to point an actual old value copy using either BOOST_CONTRACT_OLDOF or boost::contract::make_old (that is why this class does not have public non-default constructors):classu{public:virtualvoidf(...,boost::contract::virtual_*v=0){boost::contract::old_ptr<old_type>old_var=// For copyable `old_type`.BOOST_CONTRACT_OLDOF(v,old_expr);...}...};See Also: Old ValuesTemplate Parameterstypename TType of the pointed old value. This type must be copyable (i.e., boost::contract::is_old_value_copyable<T>::value must be true), otherwise this pointer will always be null and this library will generate a compile-time error when the pointer is dereferenced. old_ptr
public
construct/copy/destructold_ptr();Construct this old value pointer as null. old_ptr public member functionsTconst&operator*()const;Dereference this old value pointer. This will generate a run-time error if this pointer is null and a compile-time error if the pointed type T is not copyable (i.e., if boost::contract::is_old_value_copyable<T>::value is false).Returns:The pointed old value. Contract assertions should not change the state of the program so this member function is const and it returns the old value as a reference to a constant object (see
Constant Correctness). Tconst*operator->()const;Structure-dereference this old value pointer. This will generate a compile-time error if the pointed type T is not copyable (i.e., if boost::contract::is_old_value_copyable<T>::value is false).Returns:A pointer to the old value (null if this old value pointer is null). Contract assertions should not change the state of the program so this member function is const and it returns the old value as a pointer to a constant object (see
Constant Correctness). explicitoperatorbool()const;Query if this old value pointer is null or not (safe-bool operator). (This is implemented using safe-bool emulation on compilers that do not support C++11 explicit type conversion operators.)Returns:True if this pointer is not null, false otherwise. Class template old_ptr_if_copyable3boost::contract::old_ptr_if_copyableOld value pointer that does not require the pointed old value type to be copyable. // In header: <boost/contract/old.hpp>
template<typename T>class old_ptr_if_copyable {public:// typestypedefTelement_type;// Pointed old value type. // construct/copy/destructold_ptr_if_copyable();old_ptr_if_copyable(old_ptr<T>const&);// public member functionsTconst&operator*()const;Tconst*operator->()const;explicitoperatorbool()const;};DescriptionThis pointer can be set to point to an actual old value copy using either BOOST_CONTRACT_OLDOF or boost::contract::make_old:template<typenameT>// Type `T` might or not be copyable.classu{public:virtualvoidf(...,boost::contract::virtual_*v=0){boost::contract::old_ptr_if_copyable<T>old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...if(old_var)...// Always null for non-copyable types....}...};See Also:
Old Value RequirementsTemplate Parameterstypename TType of the pointed old value. If this type is not copyable (i.e., boost::contract::is_old_value_copyable<T>::value is false), this pointer will always be null (but this library will not generate a compile-time error when this pointer is dereferenced). old_ptr_if_copyable
public
construct/copy/destructold_ptr_if_copyable();Construct this old value pointer as null. old_ptr_if_copyable(old_ptr<T>const& other);Construct this old value pointer from an old value pointer that requires the old value type to be copyable. Ownership of the pointed value object is transferred to this pointer. This constructor is implicitly called by this library when assigning an object of this type using BOOST_CONTRACT_OLDOF (this constructor is usually not explicitly called by user code).Parameters:otherOld value pointer that requires the old value type to be copyable. old_ptr_if_copyable public member functionsTconst&operator*()const;Dereference this old value pointer. This will generate a run-time error if this pointer is null, but no compile-time error is generated if the pointed type T is not copyable (i.e., if boost::contract::is_old_value_copyable<T>::value is false).Returns:The pointed old value. Contract assertions should not change the state of the program so this member function is const and it returns the old value as a reference to a constant object (see
Constant Correctness). Tconst*operator->()const;Structure-dereference this old value pointer. This will return null but will not generate a compile-time error if the pointed type T is not copyable (i.e., if boost::contract::is_old_value_copyable<T>::value is false).Returns:A pointer to the old value (null if this old value pointer is null). Contract assertions should not change the state of the program so this member function is const and it returns the old value as a pointer to a constant object (see
Constant Correctness). explicitoperatorbool()const;Query if this old value pointer is null or not (safe-bool operator). (This is implemented using safe-bool emulation on compilers that do not support C++11 explicit type conversion operators.)Returns:True if this pointer is not null, false otherwise. Class old_value3boost::contract::old_valueConvert user-specified expressions to old values. // In header: <boost/contract/old.hpp>
class old_value {public:// construct/copy/destructtemplate<typename T>old_value(Tconst&,typenameboost::enable_if< boost::contract::is_old_value_copyable<T>>::type*=0);template<typename T>old_value(Tconst&,typenameboost::disable_if< boost::contract::is_old_value_copyable<T>>::type*=0);};DescriptionThis class is usually only implicitly used by this library and it does not explicitly appear in user code.On older compilers that cannot correctly deduce the boost::contract::is_old_value_copyable trait used in the declaration of this class, programmers can manually specialize that trait to make sure that only old value types that are copyable are actually copied.See Also:
Old Value Requirements old_value
public
construct/copy/destructtemplate<typename T>old_value(Tconst& old,typenameboost::enable_if< boost::contract::is_old_value_copyable<T>>::type*=0);Construct this object from the specified old value when the old value type is copy constructible. The specified old value old is copied (one time only) using boost::contract::old_value_copy, in which case the related old value pointer will not be null (but no copy is made if postconditions and exception guarantees are not being checked, see BOOST_CONTRACT_NO_OLDS).Parameters:oldOld value to be copied.Template Parameters:TOld value type. template<typename T>old_value(Tconst& old,typenameboost::disable_if< boost::contract::is_old_value_copyable<T>>::type*=0);Construct this object from the specified old value when the old value type is not copyable. The specified old value old cannot be copied in this case so it is not copied and the related old value pointer will always be null (thus calls to this constructor have no effect and they will likely be optimized away by most compilers).Parameters:oldOld value (that will not be copied in this case).Template Parameters:TOld value type. Struct template old_value_copy3boost::contract::old_value_copyTrait to copy an old value. // In header: <boost/contract/old.hpp>
template<typename T>struct old_value_copy {// construct/copy/destructexplicitold_value_copy(Tconst&);// public member functionsTconst&old()const;};DescriptionBy default, the implementation of this trait uses T's copy constructor to make one single copy of the specified value. However, programmers can specialize this trait to copy old values using user-specific operations different from T's copy constructor. The default implementation of this trait is equivalent to:template<typenameT>classold_value_copy{public:explicitold_value_copy(Tconst&old):old_(old)// One single copy of value using T's copy constructor.{}Tconst&old()const{returnold_;}private:Tconstold_;// The old value copy.};This library will instantiate and use this trait only on old value types T that are copyable (i.e., for which boost::contract::is_old_value_copyable<T>::value is true).See Also:
Old Value Requirements old_value_copy
public
construct/copy/destructexplicitold_value_copy(Tconst& old);Construct this object by making one single copy of the specified old value. This is the only operation within this library that actually copies old values. This ensures this library makes one and only one copy of an old value (if they actually need to be copied, see BOOST_CONTRACT_NO_OLDS).Parameters:oldThe old value to copy. old_value_copy public member functionsTconst&old()const;Return a (constant) reference to the old value that was copied. Contract assertions should not change the state of the program so the old value copy is returned as const (see
Constant Correctness). Function null_old3boost::contract::null_oldReturn a "null" old value. // In header: <boost/contract/old.hpp>
old_value null_old();DescriptionThe related old value pointer will also be null. This function is usually only called by the code expanded by BOOST_CONTRACT_OLDOF.See Also: No MacrosReturns:Null old value. Function make_old3boost::contract::make_oldMake an old value pointer (but not for virtual public functions and public functions overrides). // In header: <boost/contract/old.hpp>
old_pointer make_old(old_value const& old);DescriptionThe related old value pointer will not be null if the specified old value was actually copied. This function is usually only called by code expanded by BOOST_CONTRACT_OLDOF(old_expr) as in:boost::contract::make_old(boost::contract::copy_old()?old_expr:boost::contract::null_old())See Also: No MacrosParameters:oldOld value which is usually implicitly constructed from the user old value expression to be copied (use the ternary operator ?: to completely avoid to evaluate the old value expression when boost::contract::copy_old() is false).Returns:Old value pointer (usually implicitly converted to either boost::contract::old_ptr or boost::contract::old_ptr_if_copyable in user code). Function make_old3boost::contract::make_oldMake an old value pointer (for virtual public functions and public functions overrides). // In header: <boost/contract/old.hpp>
old_pointer make_old(virtual_ * v, old_value const& old);DescriptionThe related old value pointer will not be null if the specified old value was actually copied. This function is usually only called by code expanded by BOOST_CONTRACT_OLDOF(v, old_expr) as in:boost::contract::make_old(v,boost::contract::copy_old(v)?old_expr:boost::contract::null_old())See Also: No MacrosParameters:oldOld value which is usually implicitly constructed from the user old value expression to be copied (use the ternary operator ?: to completely avoid to evaluate the old value expression when boost::contract::copy_old(v) is false).vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual or overriding public function declaring the contract. Returns:Old value pointer (usually implicitly converted to either boost::contract::old_ptr or boost::contract::old_ptr_if_copyable in user code). Function copy_old3boost::contract::copy_oldQuery if old values need to be copied (but not for virtual public functions and public function overrides). // In header: <boost/contract/old.hpp>
boolcopy_old();DescriptionFor example, this function always returns false when both postconditions and exception guarantees are not being checked (see BOOST_CONTRACT_NO_OLDS). This function is usually only called by the code expanded by BOOST_CONTRACT_OLDOF.See Also: No MacrosReturns:True if old values need to be copied, false otherwise. Function copy_old3boost::contract::copy_oldQuery if old values need to be copied (for virtual public functions and public function overrides). // In header: <boost/contract/old.hpp>
boolcopy_old(virtual_ * v);DescriptionFor example, this function always returns false when both postconditions and exception guarantees are not being checked (see BOOST_CONTRACT_NO_OLDS). In addition, this function returns false when overridden functions are being called subsequent times by this library to support subcontracting. This function is usually only called by the code expanded by BOOST_CONTRACT_OLDOF.See Also: No MacrosParameters:vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual or overriding public function declaring the contract.Returns:True if old values need to be copied, false otherwise. Macro BOOST_CONTRACT_OLDOF3BOOST_CONTRACT_OLDOFMacro typically used to copy an old value expression and assign it to an old value pointer. // In header: <boost/contract/old.hpp>
BOOST_CONTRACT_OLDOF(...)DescriptionThe expression expanded by this macro should be assigned to an old value pointer of type boost::contract::old_ptr or boost::contract::old_ptr_if_copyable. This is an overloaded variadic macro and it can be used in the following different ways.1. From within virtual public functions and public functions overrides:BOOST_CONTRACT_OLDOF(v,old_expr)2. From all other operations:BOOST_CONTRACT_OLDOF(old_expr)Where:v is the extra parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function or public function overrides declaring the contract. old_expr is the expression to be evaluated and copied into the old value pointer. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_OLDOF(v, (old_expr)) will always work.)
On compilers that do not support variadic macros, programmers can manually copy old value expressions without using this macro (see No Macros).See Also: Old Values Header <boost/contract/override.hpp>Handle public function overrides (for subcontracting).
BOOST_CONTRACT_NAMED_OVERRIDE(type_name, func_name)
BOOST_CONTRACT_OVERRIDE(func_name)
BOOST_CONTRACT_OVERRIDES(...)Macro BOOST_CONTRACT_NAMED_OVERRIDE3BOOST_CONTRACT_NAMED_OVERRIDEDeclare an override type trait with an arbitrary name. // In header: <boost/contract/override.hpp>
BOOST_CONTRACT_NAMED_OVERRIDE(type_name, func_name)DescriptionDeclare the override type trait named type_name to pass as an explicit template parameter to boost::contract::public_function for public function overrides.See Also: Named OverridesParameters:func_nameFunction name of the public function override. This macro is called just once even if the function name is overloaded (the same override type trait is used for all overloaded functions with the same name, see
Function Overloads). (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) type_nameName of the override type trait this macro will declare. (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) Macro BOOST_CONTRACT_OVERRIDE3BOOST_CONTRACT_OVERRIDEDeclare an override type trait named override_func_name. // In header: <boost/contract/override.hpp>
BOOST_CONTRACT_OVERRIDE(func_name)DescriptionDeclare the override type trait named override_func_name to pass as an explicit template parameter to boost::contract::public_function for public function overrides. Use BOOST_CONTRACT_NAMED_OVERRIDE to generate an override type trait with a name different than override_func_name (usually not needed).See Also:
Public Function OverridesParameters:func_nameFunction name of the public function override. This macro is called just once even if the function name is overloaded (the same override type trait is used for all overloaded functions with the same name, see Function Overloads). (This is not a variadic macro parameter but it should never contain any comma because it is an identifier.) Macro BOOST_CONTRACT_OVERRIDES3BOOST_CONTRACT_OVERRIDESDeclare multiple override type traits at once naming them override_... (for convenience). // In header: <boost/contract/override.hpp>
BOOST_CONTRACT_OVERRIDES(...)DescriptionThis variadic macro is provided for convenience as BOOST_CONTRACT_OVERRIDES(f_1, f_2, ..., f_n) expands to code equivalent to:BOOST_CONTRACT_OVERRIDE(f_1)BOOST_CONTRACT_OVERRIDE(f_2)...BOOST_CONTRACT_OVERRIDE(f_n)On compilers that do not support variadic macros, the override type traits can be equivalently programmed one-by-one calling BOOST_CONTRACT_OVERRIDE for each function name as shown above.See Also:
Public Function OverridesParameters:...A comma separated list of one or more function names of public function overrides. (Each function name should never contain commas because it is an identifier.) Header <boost/contract/public_function.hpp>Program contracts for public functions (including subcontracting). The different overloads handle public functions that are static, virtual void, virtual non-void, overriding void, and overriding non-void. namespaceboost{namespacecontract{template<typename Class>
specify_precondition_old_postcondition_except public_function();template<typename Class>
specify_precondition_old_postcondition_except public_function(Class*);template<typename Class>
specify_precondition_old_postcondition_except
public_function(virtual_ *,Class*);template<typename VirtualResult,typename Class>
specify_precondition_old_postcondition_except<VirtualResult>public_function(virtual_ *,VirtualResult&,Class*);template<typename Override,typename F,typename Class,typename... Args>
specify_precondition_old_postcondition_except
public_function(virtual_ *,F,Class*,Args&...);template<typename Override,typename VirtualResult,typename F,typename Class,typename... Args>
specify_precondition_old_postcondition_except<VirtualResult>public_function(virtual_ *,VirtualResult&,F,Class*,Args&...);}}Function template public_function3boost::contract::public_functionProgram contracts for static public functions. // In header: <boost/contract/public_function.hpp>
template<typename Class>
specify_precondition_old_postcondition_except public_function();DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check static class invariants for static public functions:classu{friendclassboost::contract::access;staticvoidstatic_invariant(){// Optional (as for non-static).BOOST_CONTRACT_ASSERT(...);...}public:staticvoidf(...){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function<u>().precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body.}...};For optimization, this can be omitted for static public functions that do not have preconditions, postconditions and exception guarantees, within classes that have no static invariants.See Also: Static Public FunctionsTemplate Parameters:ClassThe type of the class containing the static public function declaring the contract. This template parameter must be explicitly specified for static public functions (because they have no object this so there is no function argument from which this type template parameter can be automatically deduced by C++).Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the static public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Function template public_function3boost::contract::public_functionProgram contracts for public functions that are not static, not virtual, and do not not override. // In header: <boost/contract/public_function.hpp>
template<typename Class>
specify_precondition_old_postcondition_except public_function(Class* obj);DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public functions that are not static, not virtual, and do not override:classu{friendclassboost::contract::access;voidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}public:voidf(...){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function(this).precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body.}...};For optimization, this can be omitted for public functions that do not have preconditions, postconditions and exception guarantees, within classes that have no invariants.See Also: Public FunctionsParameters:objThe object this from the scope of the enclosing public function declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions).Template Parameters:ClassThe type of the class containing the public function declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.)Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Function template public_function3boost::contract::public_functionProgram contracts for void virtual public functions that do not override. // In header: <boost/contract/public_function.hpp>
template<typename Class>
specify_precondition_old_postcondition_except
public_function(virtual_ * v,Class* obj);DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public functions that are virtual, do not override, and return void:classu{friendclassboost::contract::access;voidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}public:voidf(...,boost::contract::virtual_*v=0){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function(v,this).precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body.}...};A virtual public function should always call boost::contract::public_function otherwise this library will not be able to correctly use it for subcontracting.See Also: Virtual Public FunctionsParameters:objThe object this from the scope of the enclosing virtual public function declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions).vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function. Template Parameters:ClassThe type of the class containing the virtual public function declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.)Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Function template public_function3boost::contract::public_functionProgram contracts for non-void virtual public functions that do not override. // In header: <boost/contract/public_function.hpp>
template<typename VirtualResult,typename Class>
specify_precondition_old_postcondition_except<VirtualResult>public_function(virtual_ * v,VirtualResult& r,Class* obj);DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public functions that are virtual, do not override, and do not return void:classu{friendclassboost::contract::access;voidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}public:tf(...,boost::contract::virtual_*v=0){tresult;boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function(v,result,this).precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...}).postcondition([&](tconst&result){// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body (use `return result = return_expr`).}...};A virtual public function should always call boost::contract::public_function otherwise this library will not be able to correctly use it for subcontracting.See Also: Virtual Public FunctionsParameters:objThe object this from the scope of the enclosing virtual public function declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions).rA reference to the return value of the enclosing virtual public function declaring the contract. This is usually a local variable declared by the enclosing virtual public function just before the contract, but programmers must set it to the actual value being returned by the function at each return statement. vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function. Template Parameters:ClassThe type of the class containing the virtual public function declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.)VirtualResultThis type must be the same as, or compatible with, the return type of the enclosing virtual public function declaring the contract (this library might not be able to generate a compile-time error if these types mismatch, but in general that will cause run-time errors or undefined behaviour). Alternatively, boost::optional<return-type> can also be used (see
Optional Return Values). (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Function template public_function3boost::contract::public_functionProgram contracts for void public functions overrides (virtual or not). // In header: <boost/contract/public_function.hpp>
template<typename Override,typename F,typename Class,typename... Args>
specify_precondition_old_postcondition_except
public_function(virtual_ * v,F f,Class* obj,Args&... args);DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public function overrides (virtual or not) that return void:classu#defineBASESprivateboost::contract::constructor_precondition<u>, \
publicb,privatew:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}BOOST_CONTRACT_OVERRIDES(f)public:// Override from `b::f`.voidf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function<override_f>(v,&u::f,this,a_1,...,a_n).precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...}).postcondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body.}...};A public function override should always call boost::contract::public_function otherwise this library will not be able to correctly use it for subcontracting.See Also:
Public Function OverridesParameters:argsAll arguments passed to the enclosing public function override declaring the contract (by reference and in the order they appear in the enclosing function declaration), but excluding the trailing argument v.fA pointer to the enclosing public function override declaring the contract (but see
Function Overloads). objThe object this from the scope of the enclosing public function override declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions). vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing public function override. Template Parameters:ArgsThe types of all parameters passed to the enclosing public function override declaring the contract, but excluding the trailing parameter type boost::contract::virtual_*. On compilers that do not support variadic templates, this library internally implements this function using preprocessor meta-programming (in this case, the maximum number of supported arguments is defined by BOOST_CONTRACT_MAX_ARGS). (Usually these template parameters are automatically deduced by C++ and they do not need to be explicitly specified by programmers.)ClassThe type of the class containing the virtual public function declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) FThe function pointer type of the enclosing public function override declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) OverrideThe type trait override_function-name declared using the BOOST_CONTRACT_OVERRIDE or related macros. This template parameter must be explicitly specified (because there is no function argument from which it can be automatically deduced by C++). Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Function template public_function3boost::contract::public_functionProgram contracts for non-void public functions overrides (virtual or not). // In header: <boost/contract/public_function.hpp>
template<typename Override,typename VirtualResult,typename F,typename Class,typename... Args>
specify_precondition_old_postcondition_except<VirtualResult>public_function(virtual_ * v,VirtualResult& r,F f,Class* obj,Args&... args);DescriptionThis is used to specify preconditions, postconditions, exception guarantees, old value copies at body, and check class invariants for public function overrides (virtual or not) that do not return void:classu#defineBASESprivateboost::contract::constructor_precondition<u>, \
publicb,privatew:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESvoidinvariant()const{// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...}BOOST_CONTRACT_OVERRIDES(f)public:// Override from `b::f`.tf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){tresult;boost::contract::old_ptr<old_type>old_var;boost::contract::checkc=boost::contract::public_function<override_f>(v,result,&u::f,this,a_1,...,a_n).precondition([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...}).old([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...}).postcondition([&](tconst&result){// Optional.BOOST_CONTRACT_ASSERT(...);...}).except([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});...// Function body (use `return result = return_expr`).}...};A public function override should always call boost::contract::public_function otherwise this library will not be able to correctly use it for subcontracting.See Also:
Public Function OverridesParameters:argsAll arguments passed to the enclosing public function override declaring the contract (by reference and in the order they appear in the enclosing function declaration), but excluding the trailing argument v.fA pointer to the enclosing public function override declaring the contract (but see
Function Overloads). objThe object this from the scope of the enclosing public function override declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions). rA reference to the return value of the enclosing public function override declaring the contract. This is usually a local variable declared by the enclosing public function override just before the contract, but programmers must set it to the actual value being returned by the function at each return statement. vThe trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing public function override. Template Parameters:ArgsThe types of all parameters passed to the enclosing public function override declaring the contract, but excluding the trailing parameter type boost::contract::virtual_*. On compilers that do not support variadic templates, this library internally implements this function using preprocessor meta-programming (in this case, the maximum number of supported arguments is defined by BOOST_CONTRACT_MAX_ARGS). (Usually these template parameters are automatically deduced by C++ and they do not need to be explicitly specified by programmers.)ClassThe type of the class containing the virtual public function declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) FThe function pointer type of the enclosing public function override declaring the contract. (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) OverrideThe type trait override_function-name declared using the BOOST_CONTRACT_OVERRIDE or related macros. This template parameter must be explicitly specified (because there is no function argument from which it can be automatically deduced by C++). VirtualResultThis type must be the same as, or compatible with, the return type of the enclosing public function override declaring the contract (this library might not be able to generate a compile-time error if these types mismatch, but in general that will cause run-time errors or undefined behaviour). Alternatively, boost::optional<return-type> can also be used (see
Optional Return Values). (Usually this template parameter is automatically deduced by C++ and it does not need to be explicitly specified by programmers.) Returns:The result of this function must be assigned to a variable of type boost::contract::check declared explicitly (i.e., without using C++11 auto declarations) and locally just before the code of the public function body (otherwise this library will generate a run-time error, see BOOST_CONTRACT_ON_MISSING_CHECK_DECL). Header <boost/contract_macro.hpp>Allow to disable contracts to completely remove their compile-time and run-time overhead. This header automatically includes all header files boost/contract/*.hpp necessary to use its macros.Almost all the macros defined in this header file are variadic macros. On compilers that do not support variadic macros, programmers can manually code #ifndef BOOST_CONTRACT_NO_... statements instead (see
Disable Contract Compilation).
BOOST_CONTRACT_PRECONDITION(...)
BOOST_CONTRACT_POSTCONDITION(...)
BOOST_CONTRACT_EXCEPT(...)
BOOST_CONTRACT_OLD(...)
BOOST_CONTRACT_OLD_PTR(...)
BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(...)
BOOST_CONTRACT_INVARIANT(...)
BOOST_CONTRACT_INVARIANT_VOLATILE(...)
BOOST_CONTRACT_STATIC_INVARIANT(...)
BOOST_CONTRACT_CONSTRUCTOR(...)
BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(...)
BOOST_CONTRACT_DESTRUCTOR(...)
BOOST_CONTRACT_FUNCTION()
BOOST_CONTRACT_STATIC_PUBLIC_FUNCTION(...)
BOOST_CONTRACT_PUBLIC_FUNCTION(...)
BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(...)Macro BOOST_CONTRACT_PRECONDITION3BOOST_CONTRACT_PRECONDITIONProgram preconditions that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_PRECONDITION(...)DescriptionBOOST_CONTRACT_PRECONDITION(f) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_PRECONDITIONS is defined):#ifndefBOOST_CONTRACT_NO_PRECONDITIONS.precondition(f)#endifWhere:f is the nullay functor called by this library to check preconditions f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::precondition_failure). This functor should capture variables by (constant) value, or better by (constant) reference (to avoid extra copies). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Preconditions Macro BOOST_CONTRACT_POSTCONDITION3BOOST_CONTRACT_POSTCONDITIONProgram postconditions that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_POSTCONDITION(...)DescriptionBOOST_CONTRACT_POSTCONDITION(f) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_POSTCONDITIONS is defined):#ifndefBOOST_CONTRACT_NO_POSTCONDITIONS.postcondition(f)#endifWhere:f is the functor called by this library to check postconditions f() or f(result). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::postcondition_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit). This functor takes the return value (preferably by const&) result as its one single parameter f(result) but only for virtual public functions and public functions overrides, otherwise it takes no parameter f(). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Postconditions Macro BOOST_CONTRACT_EXCEPT3BOOST_CONTRACT_EXCEPTProgram exception guarantees that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_EXCEPT(...)DescriptionBOOST_CONTRACT_EXCEPT(f) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_EXCEPTS is defined):#ifndefBOOST_CONTRACT_NO_EXCEPTS.except(f)#endifWhere:f is the nullary functor called by this library to check exception guarantees f(). Assertions within this functor are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract assertion failure (and will result in this library calling boost::contract::except_failure). This functor should capture variables by (constant) references (to access the values they will have at function exit). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Exception Guarantees Macro BOOST_CONTRACT_OLD3BOOST_CONTRACT_OLDProgram old value copies at body that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_OLD(...)DescriptionBOOST_CONTRACT_OLD(f) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_OLDS is defined):#ifndefBOOST_CONTRACT_NO_OLDS.old(f)#endifWhere:f is the nullary functor called by this library f() to assign old value copies just before the body is execute but after entry invariants (when they apply) and preconditions are checked. Old value pointers within this functor call are usually assigned using BOOST_CONTRACT_OLDOF. Any exception thrown by a call to this functor will result in this library calling boost::contract::old_failure (because old values could not be copied to check postconditions and exception guarantees). This functor should capture old value pointers by references so they can be assigned (all other variables needed to evaluate old value expressions can be captured by (constant) value, or better by (constant) reference to avoid extra copies). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation,
Old Values Copied at Body Macro BOOST_CONTRACT_OLD_PTR3BOOST_CONTRACT_OLD_PTRProgram old values that can be completely disabled at compile-time for old value types that are required to be copyable. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_OLD_PTR(...)DescriptionThis is used to program old value copies for copyable types:classu{public:voidf(...){BOOST_CONTRACT_OLD_PTR(old_type_a)(old_var_a);// Null...BOOST_CONTRACT_OLD_PTR(old_type_b)(old_var_b,old_expr_b);// Set.BOOST_CONTRACT_PUBLIC_FUNCTION(this)...BOOST_CONTRACT_OLD([&]{old_var_a=BOOST_CONTRACT_OLDOF(old_expr_a);// ...set....})...;...// Function body.}virtualvoidg(...,boost::contract::virtual_*v=0){BOOST_CONTRACT_OLD_PTR(old_type_a)(old_var_a);// No `v`BOOST_CONTRACT_OLD_PTR(old_type_b)(v,old_var_b,old_expr_b);// `v`BOOST_CONTRACT_PUBLIC_FUNCTION(v,this)...BOOST_CONTRACT_OLD([&]{old_var_a=BOOST_CONTRACT_OLDOF(v,old_expr_a);// `v`...})...;...// Function body.}...};This is an overloaded variadic macro and it can be used in the following different ways (note that no code is generated when BOOST_CONTRACT_NO_OLDS is defined).1. BOOST_CONTRACT_OLD_PTR(old_type)(old_var) expands to code equivalent to the following (this leaves the old value pointer null):#ifndefBOOST_CONTRACT_NO_OLDS// This declaration does not need to use `v`.boost::contract::old_ptr<old_type>old_var#endif2. BOOST_CONTRACT_OLD_PTR(old_type)(old_var, old_expr) expands to code equivalent to the following (this initializes the pointer to the old value copy, but not to be used for virtual public functions and public function overrides):#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr<old_type>old_var=BOOST_CONTRACT_OLDOF(old_expr)#endif3. BOOST_CONTRACT_OLD_PTR(old_type)(v, old_var, old_expr) expands to code equivalent to the following (this initializes the pointer to the old value copy for virtual public functions and public function overrides):#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr<old_type>old_var=BOOST_CONTRACT_OLDOF(v,old_expr)#endifWhere:old_type is the type of the pointed old value. This type must be copyable (i.e., boost::contract::is_old_value_copyable<old_type>::value is true), otherwise this pointer will always be null and this library will generate a compile-time error when the pointer is dereferenced (see BOOST_CONTRACT_OLD_PTR_IF_COPYABLE). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) (Rationale: Template parameters like this one are specified to this library macro interface using their own set of parenthesis SOME_MACRO(template_params)(other_params).) v is the extra training parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function or public function override declaring the contract. (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) old_var is the name of the old value pointer variable. (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) old_expr is the expression to be evaluated and copied in the old value pointer. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_OLD_PTR(old_type)(v, old_var, (old_expr)) will always work.)See Also:
Disable Contract Compilation, Old Values Macro BOOST_CONTRACT_OLD_PTR_IF_COPYABLE3BOOST_CONTRACT_OLD_PTR_IF_COPYABLEProgram old values that can be completely disabled at compile-time for old value types that are not required to be copyable. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(...)DescriptionThis is used to program old value copies for types that might or might not be copyable:template<typenameT>// Type `T` might or not be copyable.classu{public:voidf(...){BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type_a)(old_var_a);BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type_b)(old_var_b,old_expr_b);BOOST_CONTRACT_PUBLIC_FUNCTION(this)...BOOST_CONTRACT_OLD([&]{old_var_a=BOOST_CONTRACT_OLDOF(old_expr_a);...})...// In postconditions or exception guarantees:if(old_var_a)...// Always null for non-copyable types.if(old_var_b)...// Always null for non-copyable types....;...// Function body.}virtualvoidg(...,boost::contract::virtual_*v=0){BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type_a)(old_var_a);BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type_b)(v,old_var_b,old_expr_b);BOOST_CONTRACT_PUBLIC_FUNCTION(v,this)...BOOST_CONTRACT_OLD([&]{old_var_a=BOOST_CONTRACT_OLDOF(v,old_expr_a);...})...// In postconditions or exception guarantees:if(old_var_a)...// Always null for non-copyable types.if(old_var_b)...// Always null for non-copyable types....;...// Function body.}...};This is an overloaded variadic macro and it can be used in the following different ways (note that no code is generated when BOOST_CONTRACT_NO_OLDS is defined).1. BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type)(old_var) expands to code equivalent to the following (this leaves the old value pointer null):#ifndefBOOST_CONTRACT_NO_OLDS// This declaration does not need to use `v`.boost::contract::old_ptr_if_copyable<old_type>old_var#endif2. BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type)(old_var, old_expr) expands to code equivalent to the following (this initializes the pointer to the old value copy, but not to be used for virtual public functions and public function overrides):#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr_if_copyable<old_type>old_var=BOOST_CONTRACT_OLDOF(old_expr)#endif3. BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type)(v, old_var, old_expr) expands to code equivalent to the following (this initializes the pointer to the old value copy for virtual public functions and public function overrides):#ifndefBOOST_CONTRACT_NO_OLDSboost::contract::old_ptr_if_copyable<old_type>old_var=BOOST_CONTRACT_OLDOF(v,old_expr)#endifWhere:old_type is the type of the pointed old value. If this type is not copyable (i.e., boost::contract::is_old_value_copyable<old_type>::value is false), this pointer will always be null, but this library will not generate a compile-time error when this pointer is dereferenced (see BOOST_CONTRACT_OLD_PTR). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) v is the extra trailing parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function or public function override declaring the contract. (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) old_var is the name of the old value pointer variable. (This is not a variadic macro parameter but it should never contain commas because it is an identifier.) old_expr is the expression to be evaluated and copied in the old value pointer. (This is not a variadic macro parameter so any comma it might contain must be protected by round parenthesis and BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(old_type)(v, old_var, (old_expr)) will always work.)See Also:
Disable Contract Compilation,
Old Value Requirements Macro BOOST_CONTRACT_INVARIANT3BOOST_CONTRACT_INVARIANTProgram (constant) class invariants that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_INVARIANT(...)DescriptionBOOST_CONTRACT_INVARIANT({ ... }) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_INVARIANTS is defined):#ifndefBOOST_CONTRACT_NO_INVARIANTSvoidBOOST_CONTRACT_INVARIANT_FUNC()const{...}#endifWhere:{ ... } is the definition of the function that checks class invariants for public functions that are not static and not volatile (see BOOST_CONTRACT_STATIC_INVARIANT and BOOST_CONTRACT_INVARIANT_VOLATILE). The curly parenthesis are mandatory (rationale: this is so the syntax of this macro resembles mote the syntax of the lambda functions usually used to specify preconditions, etc.). Assertions within this function are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this function indicates a contract assertion failure (and will result in this library calling either boost::contract::entry_invariant_failure or boost::contract::exit_invariant_failure). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Class Invariants Macro BOOST_CONTRACT_INVARIANT_VOLATILE3BOOST_CONTRACT_INVARIANT_VOLATILEProgram volatile class invariants that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_INVARIANT_VOLATILE(...)DescriptionBOOST_CONTRACT_INVARIANT_VOLATILE({ ... }) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_INVARIANTS is defined):#ifndefBOOST_CONTRACT_NO_INVARIANTSvoidBOOST_CONTRACT_INVARIANT_FUNC()constvolatile{...}#endifWhere:{ ... } is the definition of the function that checks class invariants for volatile public functions (see BOOST_CONTRACT_INVARIANT and BOOST_CONTRACT_STATIC_INVARIANT). The curly parenthesis are mandatory. Assertions within this function are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this function indicates a contract assertion failure (and will result in this library calling either boost::contract::entry_invariant_failure or boost::contract::exit_invariant_failure). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation,
Volatile Public Functions Macro BOOST_CONTRACT_STATIC_INVARIANT3BOOST_CONTRACT_STATIC_INVARIANTProgram static class invariants that can be completely disabled at compile-time. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_STATIC_INVARIANT(...)DescriptionBOOST_CONTRACT_STATIC_INVARIANT({ ... }) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_INVARIANTS is defined):#ifndefBOOST_CONTRACT_NO_INVARIANTSstaticvoidBOOST_CONTRACT_STATIC_INVARIANT_FUNC(){...}#endifWhere:{ ... } is the definition of the function that checks class invariants for static public functions (see BOOST_CONTRACT_INVARIANT and BOOST_CONTRACT_INVARIANT_VOLATILE). The curly parenthesis are mandatory. Assertions within this function are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this function indicates a contract assertion failure (and will result in this library calling either boost::contract::entry_invariant_failure or boost::contract::exit_invariant_failure). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Class Invariants Macro BOOST_CONTRACT_CONSTRUCTOR3BOOST_CONTRACT_CONSTRUCTORProgram contracts that can be completely disabled at compile-time for constructors. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_CONSTRUCTOR(...)DescriptionThis is used together with BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for constructors (see BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION to specify preconditions for constructors):classu{friendclassboost::contract::access;BOOST_CONTRACT_INVARIANT({// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...})public:u(...){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_CONSTRUCTOR(this)// No `PRECONDITION` (use `CONSTRUCTOR_PRECONDITION` if needed).BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_epxr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Constructor body.}...};For optimization, this can be omitted for constructors that do not have postconditions and exception guarantees, within classes that have no invariants.BOOST_CONTRACT_CONSTRUCTOR(obj) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_CONSTRUCTORS is defined):#ifndefBOOST_CONTRACT_NO_CONSTRUCTORSboost::contract::checkinternal_var=boost::contract::constructor(obj)#endifWhere:obj is the object this from the scope of the enclosing constructor declaring the contract. Constructors check all class invariants, including static and volatile invariants (see BOOST_CONTRACT_INVARIANT, BOOST_CONTRACT_STATIC_INVARIANT, and BOOST_CONTRACT_INVARIANT_VOLATILE). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation, Constructors Macro BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION3BOOST_CONTRACT_CONSTRUCTOR_PRECONDITIONProgram preconditions that can be disabled at compile-time for constructors. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(...)DescriptionThis is used together with BOOST_CONTRACT_CONSTRUCTOR to specify contracts for constructors. Constructors that do not have preconditions do not use this macro. When at least one of the class constructors uses this macro, boost::contract::constructor_precondition must be the first and private base of the class declaring the constructor for which preconditions are programmed:classu#defineBASESprivateboost::contract::constructor_precondition<u>, \
publicb:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASES...public:explicitu(unsignedx):BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(u)([&]{BOOST_CONTRACT_ASSERT(x!=0);}),b(1/x){...}...};BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(class_type)(f) expands to code equivalent to the following (note that when BOOST_CONTRACT_NO_PRECONDITIONS is defined, this macro trivially expands to a default constructor call that is internally implemented to do nothing so this should have minimal to no overhead):// Guarded only by NO_PRECONDITIONS (and not also by NO_CONSTRUCTORS)// because for constructor's preconditions (not for postconditions, etc.).#ifndefBOOST_CONTRACT_NO_PRECONDITIONSboost::contract::constructor_precondition<class_type>(f)#else// No-op call (likely optimized away, minimal to no overhead).boost::contract::constructor_precondition<class_type>()#endifWhere:class_type is the type of the class containing the constructor for which preconditions are being programmed. (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) f is the nullary functor called by this library to check constructor preconditions f(). Assertions within this functor call are usually programmed using BOOST_CONTRACT_ASSERT, but any exception thrown by a call to this functor indicates a contract failure (and will result in this library calling boost::contract::precondition_failure). This functor should capture variables by (constant) value, or better by (constant) reference to avoid extra copies. (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.)See Also:
Disable Contract Compilation, Constructors Macro BOOST_CONTRACT_DESTRUCTOR3BOOST_CONTRACT_DESTRUCTORProgram contracts that can be completely disabled at compile-time for destructors. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_DESTRUCTOR(...)DescriptionThis is used together with BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for destructors (destructors cannot have preconditions, see Destructor Calls):classu{friendclassboost::contract::access;BOOST_CONTRACT_INVARIANT({// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...})public:~u(){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_DESTRUCTOR(this)// No `PRECONDITION` (destructors have no preconditions).BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Destructor body.}...};For optimization, this can be omitted for destructors that do not have postconditions and exception guarantees, within classes that have no invariants.BOOST_CONTRACT_DESTRUCTOR(obj) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_DESTRUCTORS is defined):#ifndefBOOST_CONTRACT_NO_DESTRUCTORSboost::contract::checkinternal_var=boost::contract::destructor(obj)#endifWhere:obj is the object this from the scope of the enclosing destructor declaring the contract. Destructors check all class invariants, including static and volatile invariants (see
Class Invariants and
Volatile Public Functions). (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation, Destructors Macro BOOST_CONTRACT_FUNCTION3BOOST_CONTRACT_FUNCTIONProgram contracts that can be completely disabled at compile-time for (non-public) functions. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_FUNCTION()DescriptionThis is used together with BOOST_CONTRACT_PRECONDITION, BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify preconditions, postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for (non-public) functions:voidf(...){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_FUNCTION()BOOST_CONTRACT_PRECONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Function body.}This can be used to program contracts for non-member functions but also for private and protected functions, lambda functions, loops, arbitrary blocks of code, etc. For optimization, this can be omitted for code that does not have preconditions, postconditions, and exception guarantees.BOOST_CONTRACT_FUNCTION() expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_FUNCTIONS is defined):#ifndefBOOST_CONTRACT_NO_FUNCTIONSboost::contract::checkinternal_var=boost::contract::function()#endifWhere:internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation, Non-Member Functions,
Private and Protected Functions,
Lambdas, Loops, Code Blocks Macro BOOST_CONTRACT_STATIC_PUBLIC_FUNCTION3BOOST_CONTRACT_STATIC_PUBLIC_FUNCTIONProgram contracts that can be completely disabled at compile-time for static public functions. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_STATIC_PUBLIC_FUNCTION(...)DescriptionThis is used together with BOOST_CONTRACT_PRECONDITION, BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify preconditions, postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for static public functions:classu{friendclassboost::contract::access;BOOST_CONTRACT_STATIC_INVARIANT({// Optional (as for non-static).BOOST_CONTRACT_ASSERT(...);...})public:staticvoidf(...){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION(u)BOOST_CONTRACT_PRECONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Function body.}...};For optimization, this can be omitted for static public functions that do not have preconditions, postconditions and exception guarantees, within classes that have no static invariants.BOOST_CONTRACT_STATIC_PUBLIC_FUNCTION(class_type) expands to code equivalent to the following (note that no code is generated when BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS is defined):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function<class_type>()#endifWhere:class_type is the type of the class containing the static public function declaring the contract. (This is a variadic macro parameter so it can contain commas not protected by round parenthesis.) internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation, Static Public Functions Macro BOOST_CONTRACT_PUBLIC_FUNCTION3BOOST_CONTRACT_PUBLIC_FUNCTIONProgram contracts that can be completely disabled at compile-time for non-static public functions that do not override. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_PUBLIC_FUNCTION(...)DescriptionThis is used together with BOOST_CONTRACT_PRECONDITION, BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify preconditions, postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for non-static public functions (virtual or not, void or not) that do not override:classu{friendclassboost::contract::access;BOOST_CONTRACT_INVARIANT({// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...})public:// Non-virtual (same if void).tf(...){tresult;BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION(this)BOOST_CONTRACT_PRECONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(old_expr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Function body (use `return result = return_expr`).}// Virtual and void.virtualvoidg(...,boost::contract::virtual_*v=0){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION(v,this)...BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...})...;// Trailing `;` is required....// Function body.}// Virtual and non-void.virtualth(...,boost::contract::virtual_*v=0){tresult;BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION(v,result,this)...BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...})BOOST_CONTRACT_POSTCONDITION([&](tconst&result){// OptionalBOOST_CONTRACT_ASSERT(...);...})...;// Trailing `;` is required....// Function body (use `return result = return_expr`).}...};For optimization, this can be omitted for non-virtual public functions that do not have preconditions, postconditions and exception guarantees, within classes that have no invariants. Virtual public functions should always use BOOST_CONTRACT_PUBLIC_FUNCTION otherwise this library will not be able to correctly use them for subcontracting.This is an overloaded variadic macro and it can be used in the following different ways (note that no code is generated when BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS is defined).1. BOOST_CONTRACT_PUBLIC_FUNCTION(obj) expands to code equivalent to the following (for non-virtual public functions that are not static and do not override, returning void or not):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function(obj)#endif2. BOOST_CONTRACT_PUBLIC_FUNCTION(v, obj) expands to code equivalent to the following (for virtual public functions that do not override, returning void):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function(v,obj)#endif3. BOOST_CONTRACT_PUBLIC_FUNCTION(v, r, obj) expands to code equivalent to the following (for virtual public functions that do not override, not returning void):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function(v,r,obj)#endifWhere (these are all variadic macro parameters so they can contain commas not protected by round parenthesis):v is the extra parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function declaring the contract. r is a reference to the return value of the enclosing virtual public function declaring the contract. This is usually a local variable declared by the enclosing virtual public function just before the contract, but programmers must set it to the actual value being returned by the function at each return statement. obj is the object this from the scope of the enclosing public function declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions). internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation, Public Functions,
Virtual Public Functions Macro BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE3BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDEProgram contracts that can be completely disabled at compile-time for public function overrides. // In header: <boost/contract_macro.hpp>
BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(...)DescriptionThis is used together with BOOST_CONTRACT_PRECONDITION, BOOST_CONTRACT_POSTCONDITION, BOOST_CONTRACT_EXCEPT, and BOOST_CONTRACT_OLD to specify preconditions, postconditions, exception guarantees, and old value copies at body that can be completely disabled at compile-time for public function overrides (virtual or not):classu#defineBASESprivateboost::contract::constructor_precondition<u>, \
publicb,privatew:BASES{friendclassboost::contract::access;typedefBOOST_CONTRACT_BASE_TYPES(BASES)base_types;#undefBASESBOOST_CONTRACT_INVARIANT({// Optional (as for static and volatile).BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_OVERRIDES(f,g)public:// Override from `b::f`, and void.voidf(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_f)(v,&u::f,this,a_1,...,a_n)BOOST_CONTRACT_PRECONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...})BOOST_CONTRACT_POSTCONDITION([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...})BOOST_CONTRACT_EXCEPT([&]{// Optional.BOOST_CONTRACT_ASSERT(...);...});// Trailing `;` is required....// Function body.}// Override from `b::g`, and void.tg(t_1a_1,...,t_na_n,boost::contract::virtual_*v=0){tresult;BOOST_CONTRACT_OLD_PTR(old_type)(old_var);BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_g)(v,result,&u::g,this,a_1,...,a_n)...BOOST_CONTRACT_OLD([&]{// Optional.old_var=BOOST_CONTRACT_OLDOF(v,old_expr);...})BOOST_CONTRACT_POSTCONDITION([&](tconst&result){// OptionalBOOST_CONTRACT_ASSERT(...);...})...;// Trailing `;` is required....// Function body (use `return result = return_expr`).}...};Public function overrides should always use BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE otherwise this library will not be able to correctly use it for subcontracting.This is an overloaded variadic macro and it can be used in the following different ways (note that no code is generated when BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS is defined).1. BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_type)(v, f, obj, ...) expands to code equivalent to the following (for public function overrides that return void):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function<override_type>(v,f,obj,...)#endif2. BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_type)(v, r, f, obj, ...) expands to code equivalent to the following (for public function overrides that do not return void):#ifndefBOOST_CONTRACT_NO_PUBLIC_FUNCTIONSboost::contract::checkinternal_var=boost::contract::public_function<override_type>(v,r,f,obj,...)#endifWhere (these are all variadic macro parameters so they can contain commas not protected by round parenthesis):override_type is the type override_function-name declared using the BOOST_CONTRACT_OVERRIDE or related macros. v is the extra parameter of type boost::contract::virtual_* and default value 0 from the enclosing virtual public function declaring the contract. r is a reference to the return value of the enclosing virtual public function declaring the contract. This is usually a local variable declared by the enclosing virtual public function just before the contract, but programmers must set it to the actual value being returned by the function at each return statement. f is a pointer to the enclosing public function override declaring the contract. obj is the object this from the scope of the enclosing public function declaring the contract. This object might be mutable, const, volatile, or const volatile depending on the cv-qualifier of the enclosing function (volatile public functions will check volatile class invariants, see
Volatile Public Functions). ... is a variadic macro parameter listing all the arguments passed to the enclosing public function override declaring the contract (by reference and in the order they appear in the enclosing function declaration), but excluding the trailing argument v. internal_var is a variable name internally generated by this library (this name is unique but only on different line numbers so this macro cannot be expanded multiple times on the same line).See Also:
Disable Contract Compilation,
Public Function Overrides Release Notes
This section contains notes on all releases of this library (from the latest
to the oldest).
Release 1.0.1
September 12, 2019
Cleanups and small fixes:
Using std::uncaught_exceptions on C++17 compilers
onward (instead of the now obsolete std::uncaught_exception).
Fixed a few warnings.
Removed linking to Boost.System (Boost.System is now a header-only library).
Added this library to Boost's Continuous Integration (CI).
Fixed documentation typos.
Released files are part of Boost
1.72.0.
Release 1.0.0
January 6, 2018 (Il Giorno della Befana)
First Boost release:
Fixed all tests to pass as Boost regression tests (and marked those that
are expected to fail on some specific compiler/platform versions).
Adjusted build scripts to work within Boost libraries.
Updated documentation to fit as a Boost library.
Released files are part of Boost
1.67.0.
Release 0.5.0
September 2, 2017
Contracts without the macros:
Using plain C++ code instead of macros to program contracts.
The removed macros very hard to use because they required programmers
to learn a domain-specific embedded language that replaced the
usual C++ syntax for declaring functions and classes.
The removed macros also made the code less readable, increased
compilation time (because of extensive preprocessor meta-programming),
and gave cryptic compiler errors.
However, the removed macros more correctly specified contracts
in code declarations instead of definitions, and they completely
removed extra code when contracts were disabled (both of those
can be done by the current version of this library but at the cost
of manually writing some boiler-plate code which was previous automatically
handled by the macros instead, see Separate
Body Implementation and Disable
Contract Compilation).
Simplified the library by removing some extra features that were not
directly related to contract programming, specifically:
Removed loop variants (because these are rarely if ever used).
Removed named and deduced parameters (because these can be programmed
directly using Boost.Parameter).
Removed concepts (because these can be programmed directly using
Boost.ConceptCheck).
Removed emulation of virtual specifiers override,
final, and new (because override
can be programmed directly using C++11, while final
and new are rarely
if ever used).
Removed static_assert
emulation (because this can be programmed directly using C++11,
or using Boost.StaticAssert).
Ensuring that old values and return values are copied only once even
when subcontracting is used with multiple inheritance.
Improved template meta-programming algorithm that searches the inheritance
tree for subcontracting when multiple inheritance is used.
Exception specifications and function-try blocks apply also to exceptions
thrown by the contracts, and not just to exceptions thrown by the body.
Added contracts for exception guarantees (using .except(...),
etc.).
Added predefined assertion levels for "audit" and "axiom".
Added call_if and condition_if (assertions requirements
were supported also by previous revisions of this library but they were
handled by internal code generated by the contract macros).
Released files.
Release 0.4.1
This revision of the library passed Boost formal review and it was accepted
into the Boost libraries (see https://groups.google.com/forum/?fromgroups=#!topic/boost-list/jQ7OjAmos_Y).
August 20, 2012
Accepted into Boost:
Using non-fix-spaced font in Full Table of Contents section.
Added a couple of notes to the documentation.
Changed CONTRACT_MEMBER_BODY(class_type,function_name) to class_type::CONTRACT_MEMBER_BODY(function_name) so the macro can also be used to declare
derived classes avoiding using the library syntax even when the base
class has contracts.
Released files.
Release 0.4.0
June 4, 2012
Simplified syntax, added named parameters and concepts:
Simplified syntax by reducing extra parenthesis to the bare necessary
minimum (using some of the preprocessor parsing techniques originally
introduced by Boost.LocalFunction).
Postcondition old values only copy the old-of expression (e.g., copy
just vector size instead of entire vector). This improves performance
and introduces the ConstantCopyConstructible
requirement just for the old value expression type (e.g., a vector might
not be copyable while its size always is because it is an integral type).
Removed the copyable
tag.
Body defined outside the macros (so compiler-errors for definitions retain
their usual meaning).
Added CONTRACT_CLASS
macro and removed the need to duplicate declaration elements (do not
repeat function declaration, do not repeat class name in function declaration,
etc).
Using _TPL macros so
to reduce compile-time (instead of internally making all templates contract
functions so to use typename
freely).
Overloading no longer requires unique parameter names.
Added C++11-like virtual specifiers.
Added constant assertions plus constant-expressions for select assertion
if-conditions and for loop variants.
Added named and deduced parameters.
Added concept checking.
Removed the interface to use the library without the macro (programmers
were required to write too much boiler-plate code for the non-macro interface
to be actually usable, plus supporting both the macro and non-macro interfaces
limited what the macros could do).
Released files.
Release
0.3.490
March 7, 2010
Support for most/all C++ constructs:
Added support and examples for volatile,
auto, explicit,
export, extern,
friend, inline,
struct, and throw (for exception specifications).
Documented that union cannot
be contracted.
Released files.
Release
0.3.469
February 21, 2010
Support for most/all contract programming features:
Removed use of self,
variable.now, and variable.old
in writing contracts. Object this
and variables are now accessed as usual in member functions. CONTRACT_OLDOF(variable)
is used to access old values in postconditions.
Added (precondition), (postcondition),
and (body) to specify contracts within the function
signature sequence. If no preconditions then (precondition)({...}) is simply omitted from
the sequence (same for postconditions, body is mandatory instead). For
non-void functions, users can name the result argument with (postcondition)(result-name)({...}).
Changed contract class template to use same syntax as Boost.Function
(i.e., F function type).
Added support for free functions and static member functions.
Added support for subcontracting with multiple inheritance.
Added static class invariants which are always checked (also at constructors
entry, destructor exit, and by static member functions).
Added block invariants and Eiffel-like loop variants.
Added handlers to customize action on contract failure (default to std::terminate()).
Removed feature for automatic contract documentation using Doxygen (this
is not compatible with added (precondition),
(postcondition), and (body)
because Doxygen preprocessor is not capable to handle Boost.Preprocessor
sequences).
Rewritten entire documentation (now using Boost.QuickBook instead of
Doxygen).
Released files.
Release
0.2.190
November 21, 2009
Compiled on both GCC and MSVC:
Compiled using both GCC (Linux and Cygwin) and MSVC (Windows XP).
Required to use void to specify empty function argument list. This is
to comply with C++03 standard that does not allow to pass empty macro
parameters so it does not support empty preprocessor sequences ().
Released files.
Release
0.1.126
June 17, 2009
Added documentation:
Completed first documentation draft.
Released files.
Release
0.1.55
April 19, 2009
Cleaned-up first release:
Reorganized files to cleanup root directory.
Added installation program.
Released files.
Release
0.1.50
April 19, 2009
First release:
First public release.
Released files.
Bibliography
This section lists all references consulted while designing and developing
this library.
[Andrzej13] A. Krzemienski. Andrzej's
C++ blog: Preconditions. 2013.
[Bright04] W. Bright. Contract
Programming for the D Programming Language. 2004.
[Bright04b] W. Bright. Contract
Programming for the Digital Mars C++ Compiler. 2004.
[C2] Aechmea. C^2
Contract Programming add-on for C++. 2005.
[Chrome] RemObjects. Chrome:
Contract Programming for Object Pascal in .NET. 2002.
[Clarke06] L. A. Clarke and D. S. Rosenblum.
A Historical
Perspective on Runtime Assertion Checking in Software Development.
Newsletter ACM SIGSOFT Software Engineering Notes, 2006.
[Cline90] M. Cline and D. Lea. The Behaviour
of C++ Classes and Using
Annotated C++. Proc. of the Symposium on Object Oriented
Programming Emphasizing Practical Applications, Maris College, 1990.
[Ellis90] M. A. Ellis and B. Stroustrup. The
Annotated C++ Reference Manual. ANSI Base Document, Addison Wesley,
1990.
[Gautron92] P. Gautron. An Assertion
Mechanism Based on Exceptions. Fourth C++ Technical Conference,
1992.
[Hoare73] C. A. R. Hoare. Hints on Programming
Language Design. Stanford University Artificial Intelligence memo
AIM-224/STAN-CS-73-403, pages 193-216, 1973.
[CodeContracts] Microsoft Research. Code
Contracts: Design-By-Contract Programming for All .NET Programming Languages.
2012.
[iContract] O. Enseling. iContract:
Contract Programming for Java. 2001.
[Jcontract] Parasoft. Jcontract:
Contract Programming for Java.
[Lindrud04] J. Lindrud. Design
by Contract in C++. 2004.
[Maley99] D. Maley and I. Spence. Emulating
Design by Contract in C++. Proceedings of TOOLS, IEEE Computer
Society, 1999.
[Meyer97] B. Meyer. Object Oriented
Software Construction. Prentice-Hall, 2nd edition, 1997.
[Mitchell02] R. Mitchell and J. McKim. Design
by Contract, by Example. Addison-Wesley, 2002.
[N1613] T. Ottosen. Proposal
to add Design by Contract to C++. The C++ Standards Committee,
N1613, 2004.
[N1653] C. Nelson. Working
draft changes for C99 preprocessor synchronization. C++
Standards Committee, N1653, 2004.
[N1669] T. Ottosen. Proposal
to add Contract Programming to C++ (revision 1). The C++
Standards Committee, N1669, 2004.
[N1773] D. Abrahams, L. Crowl, T. Ottosen, and J.
Widman. Proposal
to add Contract Programming to C++ (revision 2). The C++
Standards Committee, N1773, 2005.
[N1866] L. Crowl and T. Ottosen. Proposal
to add Contract Programming to C++ (revision 3). The C++
Standards Committee, N1866, 2005.
[N1895] H. Sutter and F. Glassborow. Delegating
Constructors (revision 2). C++ Standards Committee, N1895,
2005.
[N1962] L. Crowl and T. Ottosen. Proposal
to add Contract Programming to C++ (revision 4). The C++
Standards Committee, N1962, 2006.
[N2081] D. Gregor and B. Stroustrup. Concepts
(revision 1). The C++ Standards Committee, N2081, 2006.
[N2887] G. Dos Reis, B. Stroustrup, and A. Meredith.
Axioms:
Semantics Aspects of C++ Concepts. The C++ Standards Committee,
N2887, 2009.
[N2914] P. Becker. Working
Draft, Standard for Programming Language C++. The C++ Standards
Committee, N2914, 2009.
[N2906] B. Stroustrup. Simplifying
the sue of concepts. The C++ Standards Committee, N2906,
2009.
[N3248] J. Lakos. noexcept
Prevents Library Validation. The C++ Standards Committee,
N3248, 2011.
[N4154] D. Krauss. Operator
assert. The C++ Standards Committee,
N4154, 2014.
[N4160] A. Krzemienski. Value
constraints. The C++ Standards Committee, N4160, 2014.
[N4248] A. Meredith. Library
Preconditions are a Language Feature. The C++ Standards
Committee, N4248, 2014.
[N4293] J. D. Garcia. C++
language support for contract programming. The C++ Standards
Committee, N4293, 2014.
[N4378] J. Lakos, N. Myers, A. Zakharov, and A.
Beels. Language
Support for Contract Assertions (Revision 10). The C++ Standards
Committee, N4378, 2015.
[Nana] P. J. Maker. GNU
Nana. 2014.
[N4378] J. Lakos and N. Myers. FAQ
about Contract Assertions. The C++ Standards Committee,
N4379, 2015.
[N4435] W. E. Brown. Proposing
Contract Attributes. The C++ Standards Committee, N4435,
2015.
[P0147] L. Crowl. The
Use and Implementation of Contracts. The C++ Standards Committee,
P0147R0, 2015.
[P0166] J. D. Garcia. Three
interesting questions about contracts. The C++ Standards
Committee, P0166R0, 2015.
[P0246] N. Myers. Criteria
for Contract Support Merged Proposal. The C++ Standards
Committee, P0246R0, 2016.
[P0287] G. Dos Reis, J.D. Garcia, F. Logozzo, M.
Fahndrich, S. Lahiri. Simple
Contracts for C++ (R1). The C++ Standards Committee, P0287R0,
2016.
[P0380] G. Dos Reis, J.D. Garcia, J. Lakos, A. Meredith,
N. Myers, and B. Stroustrup. A
Contract Design. The C++ Standards Committee, P0380R1, 2016.
[P0542] G. Dos Reis, J.D. Garcia, J. Lakos, A. Meredith,
N. Myers, and B. Stroustrup. Support
for contract based programming in C++. The C++ Standards
Committee, P0542R0, 2017.
[Rosenblum95] D. S. Rosenblum. A
practical Approach to Programming With Assertions. IEEE
Transactions on Software Engineering, 1995.
[SPARKAda] Praxis. SPARKAda
(Ada-like Language with Contract Programming).
[SpecSharp] Microsoft. Spec#
(C# Extension).
[Stroustrup94] B. Stroustrup. The
Design and Evolution of C++. Addison Wesley, 1994.
[Stroustrup13] B. Stroustrup. The
C++ Programming Language. Addison Wesley, 4th Edition, 2013.
[Tandin04] A. Tandin. Design
by Contract macros for C++ and link to Doxygen. 2004.
[Wilson06] M. Wilson. Contract
Programming 101 - The Nuclear Reactor and the Deep Space Probe.
The C++ Source, 2006.
Acknowledgments
This section tries to recognize the contributions of all the different people
that participated directly or indirectly to the design and development of this
library.
Sincere thanks to my parents for their support with my education and my studies
in computer science.
Many thanks to Andrzej Krzemienski for reviewing early versions of this library
providing valuable insights and exchanging early ideas on assertion requirements.
Many thanks to Vicente J. Botet Escriba for reviewing earlier versions of this
library providing valuable insights and for suggesting to use a dedicated trait
to copy old values.
Thanks to Steven Watanabe for providing valuable insights on C++, SFINAE, and
introspection.
Thanks to Dave Abrahams for moderating the Boost review of this library.
Thanks to Daniel James for his help with incorporating this library files into
the Boost Git repository.
Thanks to James E. King III for integrating this library with Boost's Continuous
Integration (CI).
Thanks to David Maley for sharing source code form his inspiring work on emulating
contract programming and subcontracting in C++ in [Maley99].
Many thanks to Thorsten Ottosen for his work on the [N1962]
proposal (and its previous revisions) and for clarifying the proposal requirements
directly with the library authors when needed.
Many thanks to Bertrand Meyer for his pioneering and thorough work on contract
programming in [Meyer97].
Finally, many thanks to the entire Boost community and mailing
list for providing valuable comments on this library and great insights
on the C++ programming language.