|  | Home | Libraries | People | FAQ | More | 
“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 detailed 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.
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 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 preprocessors and other tools external to the C++ preprocessor and language itself). | 
Contract programming is characterized by the following assertion mechanisms:
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), while contract assertions for exception guarantees can be used to specify strong exception safety guarantees for given operations 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).
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 
          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  | 
        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.
      
        A limited form of contract programming is the use of 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 its preconditions
            can be kept enabled given the library cannot predict changes in the user
            code that will be calling the library). 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 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 suffers of these limitations.
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]:
        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 we reach
        the second iterator. However, in case the iterator range is invalid, 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).
      
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:
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 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 applications, but a reasonable approach often is to (see Disable Contract Checking):
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.
        A call to a non-member function with a contract executes the following steps
        (see boost::contract::function):
      
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 subcontracting).
Let's consider a public function in a derived class that overrides public virtual functions declared 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 the public branches of the inheritance tree (i.e., not just the derived class's direct public parents are inspected, but also all its public grandparents, etc.). In case of multiple inheritance this search also extends widely to all multiple public base classes following their order of declaration in the derived class inheritance list (as usual in C++, 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):
      
AND
            non-static class invariants for all overridden bases, AND
            then check the derived class static AND
            non-static invariants.
          OR
            with each other, OR
            else check the overriding function preconditions in the derived class.
          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).
          AND
            with each other, AND
            then check the overriding function postconditions in the derived class.
          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.
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 
          In this documentation
           
          As indicated by the steps above and in accordance with the substitution
          principle, subcontracting checks preconditions in  | 
        A call to a non-static public function with a contract (that does not override
        functions from any of the public base classes) executes the following steps
        (see boost::contract::public_function):
      
AND
            non-static invariants (but none of the invariants from base classes).
          AND
            non-static invariants (even if the body threw an exception, but none
            of the invariants from 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).
        A call to a static public function with a contract executes the following
        steps (see boost::contract::public_function):
      
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).
      
        A call to a constructor with a contract executes the following steps (see
        boost::contract::constructor_precondition
        and boost::contract::constructor):
      
AND
                  volatile class invariants (because the object is now successfully
                  constructed).
                oldof(*this) because there was no object before
                  the execution of the constructor body).
                oldof(*this) because there was no object before the
            execution of the constructor body, plus they can only access class static
            members because the object was not successfully constructed upon the
            constructor body throwing an exception).
          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).
        A call to a destructor with a contract executes the following steps (see
        boost::contract::destructor):
      
AND
            non-static AND
            volatile class invariants.
          oldof(*this) because there is no object after
                  successful execution of the destructor body). [12]
                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).
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 
          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  | 
        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, const
        volatile, 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 enforces 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).
      
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| In general, it is the responsibility of the programmers to code assertions that only check, and do not change, program variables. [13] | 
Contracts are part of the program specifications 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, for applications where this requirement is truly important).
        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 the 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.)
        [14]
      
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.
        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). [15]
      
| ![[Note]](../../../../../doc/src/images/note.png) | Note | 
|---|---|
| 
          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  | 
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.
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 has gain some traction within the C++ standard committee but unfortunately only supports preconditions and postconditions, while does not support class invariants, old values, and subcontracting), the Eiffel and D programming languages:
| Feature | This Library | [N1962] Proposal (not accepted in C++) | [P0380] Proposal (being considered for C++2x) | ISE Eiffel 5.4 (see [Meyer97]) | D (see [Bright04]) | 
|---|---|---|---|---|---|
| Keywords and specifiers | 
                  Specifiers:  | 
                  Keywords:  | 
                  Attributes:  | 
                  Keywords:  | 
                  Keywords:  | 
| On contract failures | 
                  Print an error to  | 
                  Call  | 
                  Call  | Throw exceptions. | Throw exceptions. | 
| Return values in postconditions | Yes, captured by or passed as a parameter to (for virtual functions) the postcondition functor. | 
                  Yes,  | 
                  Yes,  | 
                  Yes,  | 
                  Yes,  | 
| Old values in postconditions | 
                  Yes,  | 
                  Yes,  | No. | 
                  Yes,  | 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  | 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,  | 
| Subcontracting | 
                  Yes, also supports subcontracting for multiple inheritance ( | Yes, also supports subcontracting for multiple inheritance, but preconditions cannot be subcontracted. [a] | 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  | No, assertions only (use of only public functions to program preconditions is recommended but not prescribed). | No, assertions only (in addition only public members can be used in preconditions). | 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. | 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  | Yes for class invariants and postconditions, but preconditions disable no assertion. | No. | Yes. | No. | 
| Nested member function calls | Disable nothing. [c] | 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  | 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. | 
| [a] 
                    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  [b] 
                    Rationale: Theoretically, it
                    can be shown that an incorrect argument might be passed to the
                    function body when assertion checking is disabled while checking
                    preconditions (see Re:
                    [boost] [contract] diff n1962). However, that possibility
                    is limited to contract checking when an incorrect argument will
                    simply fail the contract and call the related contract failure
                    handler as expected anyway. In any case, because of that [N1962] does not disable any assertion
                    while checking preconditions. That makes it possible to have
                    infinite recursion while checking preconditions so Eiffel disables
                    assertion checking also while checking preconditions. Therefore,
                    this library by default disables assertion checking also while
                    checking preconditions, but it also provides the  [c] 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 in [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. | |||||
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 the references consulted during the design and development of this library):
| Reference | Language | Notes | 
|---|---|---|
| Digital Mars C++ | The Digital Mars C++ compiler extends C++ adding contract programming language support (among many other features). | |
| 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.) | |
| 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). | |
| C++ | Interestingly, these contract macros automatically generate Doxygen documentation [a] 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). | |
| 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  | |
| C++ | This uses an external preprocessing tool (the authors could no longer find this project's code to evaluate it). | |
| Java | This uses an external preprocessing tool. | |
| Java | This uses an external preprocessing tool. | |
| .NET | Microsoft contract programming for .NET programming languages. | |
| C# | This is a C# extension with contract programming language support. | |
| Object Pascal | This is the .NET version of Object Pascal and it has language support for contract programming. | |
| Ada | This is an Ada-like programming language with support for contract programming. | |
| [a] 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. | ||
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):
[7] 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 generally prefer to explicitly mention "this operation has no preconditions..." or "this operation has preconditions...".
[8] Rationale: Contract assertions for exception guarantees were first introduced by this library (even if exception safety guarantees have long been part of C++ STL documentation). Contract assertions for exception safety guarantees are not part of [N1962] or other references listed in the Bibliography.
[9] Rationale: Static and volatile class invariants were first introduced by this library to reflect the fact that C++ supports both static and volatile public functions. Static and volatile class invariants are not part of [N1962] or other references listed in the Bibliography.
[10] 
            Rationale: BOOST_CONTRACT_DISABLE_THREADS
            is named after BOOST_DISABLE_THREADS.
          
[11] 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).
[12] 
                    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).
                  
[13] 
            Note that this is true when using C-style assert
            as well.
          
[14] Rationale: 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 not necessary the best approach for C++).
[15] 
          Rationale: This customizable failure handling
          mechanism is similar to the one used by C++ std::terminate
          and also to the one proposed in [N1962].
        
[16] 
              For example, the following pseudocode attempts to emulate old values
              using [P0380] (scope_exit
              here is an RAII object that executes the nullary functor passed to
              its constructor when it is destroyed):
void fswap(file& x, file& y) [[expects: x.closed()]] [[excepts: y.closed()]] // Postconditions in function definition below to emulate old values. { file old_x = x; // Emulate old values with local copies (not disabled). file old_y = y; scope_exit ensures([&] { // Check after local objects destroyed. if(!std::uncaught_exception()) { // Check only if no throw. [[assert: x.closed()]] [[assert: y.closed()]] [[assert: x == old_y]] [[assert: y == old_x]] } }); x.open(); scope_exit close_x([&] { x.close(); }); y.open(); scope_exit close_y([&] { y.close(); }); file t = file::temp(); t.open; scope_exit close_t([&] { t.close(); }); x.mv(t); y.mv(x); t.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).
            
[17] For example, the following pseudocode attempts to emulation of class invariants using [P0380]:
template<typename T> class vector { bool invariant() const { // Check invariants at... [[assert: empty() == (size() == 0)]] [[assert: size() <= capacity()]] return true; } public: vector() [[ensures: invariant()]] // ...constructor exit (only if no throw). { ... } ~vector() noexcept [[expects: invariant()]] // ...destructor entry. { ... } void push_back(T const& 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).