Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

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 Value Copies at Body
Named Overrides
Access Specifiers
Throw on Failures (and noexcept)

This section is a guide to advanced usages of this library.

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<typename Iterator>
class range {
public:
    // Pure virtual function declaration (contract in definition below).
    virtual Iterator begin(boost::contract::virtual_* v = 0) = 0;

    /* ... */
};

// Pure virtual function default implementation (out-of-line in C++).
template<typename Iterator>
Iterator range<Iterator>::begin(boost::contract::virtual_* v) {
    Iterator result; // As usual, virtual pass `result` right after `v`...
    boost::contract::check c = boost::contract::public_function(v, result, this)
        .postcondition([&] (Iterator const& result) {
            if(empty()) BOOST_CONTRACT_ASSERT(result == end());
        })
    ;

    // Pure function body (never executed by this library).
    assert(false);
    return result;
}

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): [52]

class u { // Some base class.
public:
    virtual void f(boost::contract::virtual_* v = 0) {
        boost::contract::check c = 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. In other words, the code above has the effect as declaring the virtual public function in the base class with a single precondition BOOST_CONTRACT_ASSERT(true) that will always trivially pass:

class u { // Some base class.
public:
    virtual void f(boost::contract::virtual_* v = 0) {
        boost::contract::check c = 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<typename T>
class generic_unary_pack {
public:
    virtual void _1(T const& value, boost::contract::virtual_* v = 0) = 0;
    virtual T _1(boost::contract::virtual_* v = 0) const = 0;
};

template<typename T>
void generic_unary_pack<T>::_1(T const& value, boost::contract::virtual_* v) {
    boost::contract::check c = 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 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.

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). [53] For example (see optional_result.cpp):

template<unsigned Index, typename T>
T& get(std::vector<T>& vect) {
    boost::optional<T&> result; // Result not initialized here...
    boost::contract::check c = 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 proper 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 all return statements in the function are of the form:

boost::optional<return_type> result;
...
return *(result = return_expr); // 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-type const&> const&. For example (see optional_result_virtual.cpp):

template<typename T>
T& accessible<T>::at(unsigned index, boost::contract::virtual_* v) {
    boost::optional<T&> result;
    // Pass `result` right after `v`...
    boost::contract::check c = 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<T const&> 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). [54]

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 usage from within the class, base classes, and friend classes or functions. When programmers decide to specify contracts for private and protected functions, they shall 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):

class counter {
protected: // Protected functions use `function()` (like non-members).
    void set(int n) {
        boost::contract::check c = 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).
    void dec() {
        boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get());
        boost::contract::check c = 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);
    }

    int n_;

    /* ... */

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). [55] 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):

class counter {
    // Virtual private and protected functions still declare extra
    // `virtual_* = 0` parameter (otherwise they cannot be overridden), but...
protected:
    virtual void set(int n, boost::contract::virtual_* = 0) {
        boost::contract::check c = boost::contract::function() // ...no `v`.
            .precondition([&] {
                BOOST_CONTRACT_ASSERT(n <= 0);
            })
            .postcondition([&] {
                BOOST_CONTRACT_ASSERT(get() == n);
            })
        ;

        n_ = n;
    }

private:
    virtual void dec(boost::contract::virtual_* = 0) {
        boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get()); // ...no `v`.
        boost::contract::check c = 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);
    }

    int n_;

    /* ... */

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):

class counter10
    #define BASES public counter
    : BASES
{
public:
    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
    #undef BASES

    // Overriding from non-public members so no subcontracting, no override_...

    virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = boost::contract::public_function(v, this)
            .precondition([&] {
                BOOST_CONTRACT_ASSERT(n % 10 == 0);
            })
            .postcondition([&] {
                BOOST_CONTRACT_ASSERT(get() == n);
            })
        ;

        counter::set(n);
    }

    virtual void dec(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get());
        boost::contract::check c = 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):

class countable {
public:
    void invariant() const {
        BOOST_CONTRACT_ASSERT(get() <= 0);
    }

    virtual void dec(boost::contract::virtual_* v = 0) = 0;
    virtual void set(int n, boost::contract::virtual_* v = 0) = 0;
    virtual int get(boost::contract::virtual_* v = 0) const = 0;
};

/* ... */

class counter10
    #define BASES public countable, public counter // Multiple inheritance.
    : BASES
{
public:
    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
    #undef BASES

    // Overriding from public members from `countable` so use `override_...`.

    virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = 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);
    }

    virtual void dec(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get());
        boost::contract::check c = 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)

    /* ... */

[Warning] Warning

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, but that can correctly be done on GCC or Clang instead.

Friend functions are not member functions so boost::contract::function can used to program contracts for them and all considerations made in Non-Member Functions apply. For example (see friend.cpp):

class buffer;

class byte {
    friend bool operator==(buffer const& left, byte const& right);

private:
    char value_;

    /* ... */

class buffer {
    // Friend functions are not member functions...
    friend bool operator==(buffer const& left, byte const& right) {
        // ...so check contracts via `function` (which won't check invariants).
        boost::contract::check c = boost::contract::function()
            .precondition([&] {
                BOOST_CONTRACT_ASSERT(!left.empty());
                BOOST_CONTRACT_ASSERT(!right.empty());
            })
        ;

        for(char const* x = left.values_.c_str(); *x != '\0'; ++x) {
            if(*x != right.value_) return false;
        }
        return true;
    }

private:
    std::string values_;

    /* ... */

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): [56]

template<typename T>
class positive {
public:
    void invariant() const {
        BOOST_CONTRACT_ASSERT(value() > 0);
    }

    // Can be considered an extension of enclosing class' public interface...
    friend void swap(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::check c = 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);
            })
        ;

        T saved = object.value_;
        object.value_ = value;
        value = saved;
    }

private:
    T value_;

    /* ... */

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.
friend void f(class1& object1, class2* object2, type3& value3) {
    // Check preconditions.
    boost::contract::check pre = boost::contract::function()
        .precondition([&] {
            BOOST_CONTRACT_ASSERT(object2 != nullptr);
            ...
        })
    ;
    // Check class invariants for each object (programmers chose the order).
    boost::contract::check inv1 = boost::contract::public_function(&object1);
    boost::contract::check inv2 = boost::contract::public_function(object2);
    // Check postconditions and exception guarantees.
    boost::contract::check post_except = 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 the order could have been inverted if programmers so chose).

[Note] Note

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.)

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++). [57] For example, note how static_cast is used in the following calls to boost::contract::public_function (see overload.cpp):

class string_lines
    #define BASES public lines
    : BASES
{
public:
    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
    #undef BASES

    BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads.

    std::string str(boost::contract::virtual_* v = 0) const /* override */ {
        std::string result;
        boost::contract::check c = 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
        );

        return result = str_;
    }

    // Overload on (absence of) `const` qualifier.
    std::string& str(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = 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
        );

        return str_;
    }

    BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads.

    void put(std::string const& x,
            boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::old_ptr<std::string> old_str =
                BOOST_CONTRACT_OLDOF(v, str());
        boost::contract::check c = boost::contract::public_function<
                override_put>(
            v,
            // `static_cast` resolves overloaded function pointer ambiguities.
            static_cast<void (string_lines::*)(std::string const&,
                    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.
    void put(char x, boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::old_ptr<std::string> old_str =
                BOOST_CONTRACT_OLDOF(v, str());
        boost::contract::check c = 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).
    void put(int x, bool tab = false,
            boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::old_ptr<std::string> old_str =
                BOOST_CONTRACT_OLDOF(v, str());
        boost::contract::check c = 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::ostringstream s;
                s << x;
                BOOST_CONTRACT_ASSERT(
                        str() == *old_str + (tab ? "\t" : "") + s.str() + '\n');
            })
        ;

        std::ostringstream s;
        s << str_ << (tab ? "\t" : "") << x << '\n';
        str_ = s.str();
    }

private:
    std::string str_;
};

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.

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):

int total = 0;
std::for_each(v.cbegin(), v.cend(),
    // Contract for a lambda function.
    [&total] (int const x) {
        boost::contract::old_ptr<int> old_total =
                BOOST_CONTRACT_OLDOF(total);
        boost::contract::check c = boost::contract::function()
            .precondition([&] {
                BOOST_CONTRACT_ASSERT(
                        total + x <= std::numeric_limits<int>::max());
            })
            .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):

int total = 0;
// Contract for a for-loop (same for while- and all other loops).
for(std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
    boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLDOF(total);
    boost::contract::check c = boost::contract::function()
        .precondition([&] {
            BOOST_CONTRACT_ASSERT(
                    total + *i <= std::numeric_limits<int>::max());
        })
        .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::check c = 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).

/* ... */

Finally, at the moment this library does not support contracts for functions and classes declared constexpr. [58]

This library provides a mechanism to check assertions within implementation code a part from preconditions, postconditions, exceptions guarantees, and class invariants. 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):

int main() {
    // Implementation checks (via nullary functor).
    boost::contract::check c = [&] {
        BOOST_CONTRACT_ASSERT(gcd(12, 28) == 4);
        BOOST_CONTRACT_ASSERT(gcd(4, 14) == 2);
    };

    return 0;
}

The implementation check functor should capture all the variables that it needs to assert the implementation checks. These variables can be captured by value when the overhead of copying such variables is acceptable. In any case, implementation checks should not 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 (this is not a variadic macro, see No Macros):

BOOST_CONTRACT_ASSERT(bool_cond)
// Or, if `bool_cond` contains commas `,` not already within parenthesis `()`...
BOOST_CONTRACT_ASSERT((bool_cond)) // ...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 and, 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 disable when NDEBUG is defined, implementation checks are disabled when BOOST_CONTRACT_NO_CHECKS is defined. 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 overhead of implementation checks when BOOST_CONTRACT_NO_CHECKS is defined (this is not a variadic macro):

BOOST_CONTRACT_CHECK(bool_cond)
// Or, if `bool_cond` contains commas `,` not already within parenthesis `()`...
BOOST_CONTRACT_CHECK((bool_cond)) // ...use extra parenthesis (not a variadic macro).

For example (see check_macro.cpp):

int main() {
    // Implementation checks (via macro, disable run-/compile-time overhead).
    BOOST_CONTRACT_CHECK(gcd(12, 28) == 4);
    BOOST_CONTRACT_CHECK(gcd(4, 14) == 2);

    return 0;
}

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). [59] 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 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).

(See Disable Contract Checking and Disable Contract Compilation for macros to completely remove run- and compile-time overhead also for preconditions, postconditions, exception guarantees, and class invariants.)

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. This is 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 old values should be copied before executing the function body but after checking entry class invariants and preconditions (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 passed to 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). [60]

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 valid range index < s.size(). Therefore, old_y 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):

char replace(std::string& s, unsigned index, char x) {
    char result;
    boost::contract::old_ptr<char> old_y; // Null, old value copied later...
    boost::contract::check c = boost::contract::function()
        .precondition([&] {
            BOOST_CONTRACT_ASSERT(index < s.size());
        })
        .old([&] { // ...after preconditions (and invariants) checked.
            old_y = BOOST_CONTRACT_OLDOF(s[index]);
        })
        .postcondition([&] {
            BOOST_CONTRACT_ASSERT(s[index] == x);
            BOOST_CONTRACT_ASSERT(result == *old_y);
        })
    ;

    result = s[index];
    s[index] = x;
    return result;
}

The functor passed to .old(...) should capture all variables it needs to evaluate to copy 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 make copies of the values the captured variables will have just before executing the function body, and not copy the values these variables had when the functor passed to .old(...) was first declared). In any case, the functor passed to .old(...) should modify only old values and not the values of other captured variables (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.).

[Note] Note

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). [61]

As seen in Public Function Overrides, the BOOST_CONTRACT_OVERRIDE macro has to be used to declare a type override_... that is passed 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__... (which are reserved by 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: [62]

BOOST_CONTRACT_OVERRIDE(func_name)                  // Generate `override_...`.
BOOST_CONTRACT_NAMED_OVERRIDE(type_name, func_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 in C++ because it contains double underscores __). thus BOOST_CONTRACT_NAMED_OVERRIDE(override1, _1) is used to name the type override1 instead (see named_override.cpp):

template<typename T>
class positive_unary_pack
    #define BASES public generic_unary_pack<T>
    : BASES
{
public:
    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
    #undef BASES

    // BOOST_CONTRACT_OVERRIDE(_1) would generate reserved name `override__1`.
    BOOST_CONTRACT_NAMED_OVERRIDE(override1, _1) // Generate `override1`.

    virtual void _1(T const& value, boost::contract::virtual_* v = 0)
            /* override */ {
        // Use `override1` generated by BOOST_CONTRACT_NAMED_OVERRIDE above.
        boost::contract::check c = boost::contract::public_function<override1>(
            v,
            static_cast<void (positive_unary_pack::*)(T const&,
                    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). [63]

As we have seen so far, programmers are required to decorate their classes declaring the following extra members that are internally used by this library to check contracts:

In general, these members must be declared public in the user class in order for this library to be able to access them. [65] 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<typename T>
class vector
    #define BASES public pushable<T>
    : BASES
{
    friend class boost::contract::access; // Friend `access` class so...

    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // ...private bases.
    #undef BASES

    void invariant() const { // ...private invariants.
        BOOST_CONTRACT_ASSERT(size() <= capacity());
    }

    BOOST_CONTRACT_OVERRIDE(push_back) // ...private overrides.

public:
    void push_back(T const& value, boost::contract::virtual_* v = 0)
            /* override */ {
        boost::contract::old_ptr<unsigned> old_size =
                BOOST_CONTRACT_OLDOF(v, size());
        boost::contract::check c = 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, but programmers are encouraged to use it in real code.

[Warning] Warning

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.

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:

By default, these contract failure handlers print a message to the standard error std::cerr and then terminate the program calling std::terminate. [66] However, programmers can override the default contract failure handlers to perform any custom action on contract failure using the following functions respectively:

These set_..._failure(f) function calls return the contract failure handler functor f that they take as input parameter. [67] For example (see throw_on_failure.cpp):

int main() {
    boost::contract::set_precondition_failure(
    boost::contract::set_postcondition_failure(
    boost::contract::set_invariant_failure(
    boost::contract::set_old_failure(
        [] (boost::contract::from where) {
            if(where == boost::contract::from_destructor) {
                // Shall not throw from C++ destructors.
                std::clog << "ignored destructor contract failure" << std::endl;
            } else throw; // Re-throw (assertion_failure, user-defined, etc.).
        }
    ))));
    boost::contract::set_except_failure(
        [] (boost::contract::from where) {
            // 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 value copies 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 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).
  • 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).
  • 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++).
[Note] Note

It is the responsibility of the programmers to decide how to handle contract failures from destructors when they program 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).

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) throw exception-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 he stack, see throw_on_failure.cpp):

struct too_large_error {};

template<unsigned MaxSize>
class cstring
    #define BASES private boost::contract::constructor_precondition<cstring< \
            MaxSize> >
    : BASES
{

public:
    /* implicit */ cstring(char const* chars) :
        boost::contract::constructor_precondition<cstring>([&] {
            BOOST_CONTRACT_ASSERT(chars); // Throw `assertion_failure`.
            // Or, throw user-defined exception.
            if(std::strlen(chars) > MaxSize) throw too_large_error();
        })
    {

    /* ... */
};

Finally, note that the exception specifiers noexcept (since C++11) and throw (deprecated in C++11) of the enclosing operation 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):

struct too_large_error {};

template<unsigned MaxSize>
class cstring
    #define BASES private boost::contract::constructor_precondition<cstring< \
            MaxSize> >
    : BASES
{

public:
    void invariant() const {
        if(size() > MaxSize) throw too_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::check c = 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.
    }
);

/* ... */



[52] This consequence of the substitution principle that 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]).

[53] Rationale: This library uses boost::optional instead of std::optional because std::optional is not available before C++17.

[54] 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.

[55] 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.

[56] 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 adds 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).

[57] 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.

[58] Rationale: In general, it might be useful to specify contracts for constexpr functions and literal classes. However, the 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).

[59] Of course, nothing prevents programmers from calling functors 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 { ... } ()).

[60] 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).

[61] 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).

[62] 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).

[63] 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.

[64] Rationale: 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.

[65] 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 the boost::contract::access class friend as shown in this section allows to always declare the extra members private on all compilers.

[66] 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 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 operation 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.

[67] 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).


PrevUpHomeNext