mirror of
https://github.com/boostorg/contract.git
synced 2026-02-23 15:42:18 +00:00
added all release files for 0.3.469
This commit is contained in:
1
example/myvector/README.txt
Executable file
1
example/myvector/README.txt
Executable file
@@ -0,0 +1 @@
|
||||
This is the main example used in the library documentation.
|
||||
32
example/myvector/basic_begin.hpp
Executable file
32
example/myvector/basic_begin.hpp
Executable file
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
// Base class for a myvector subcontracting example.
|
||||
|
||||
#ifndef BASIC_BEGIN_HPP_
|
||||
#define BASIC_BEGIN_HPP_
|
||||
|
||||
//[ basic_begin_cpp
|
||||
|
||||
#include <contract.hpp>
|
||||
|
||||
template<class ConstIter>
|
||||
class basic_begin {
|
||||
|
||||
CONTRACT_INVARIANT( ({}) )
|
||||
|
||||
public:
|
||||
virtual ConstIter begin(void) const
|
||||
CONTRACT_FUNCTION( (class) (basic_begin)
|
||||
(public) (virtual) (ConstIter) (begin)( (void) ) (const)
|
||||
(body) ({
|
||||
return ConstIter(); // Dummy implementation (for example only).
|
||||
}) )
|
||||
};
|
||||
|
||||
//]
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
34
example/myvector/boundable.hpp
Executable file
34
example/myvector/boundable.hpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
// Base class for a myvector subcontracting example.
|
||||
|
||||
#ifndef BOUNDABLE_HPP_
|
||||
#define BOUNDABLE_HPP_
|
||||
|
||||
//[ boundable_cpp
|
||||
|
||||
#include <contract.hpp>
|
||||
|
||||
template<class ConstIter>
|
||||
class boundable {
|
||||
|
||||
CONTRACT_INVARIANT( ({
|
||||
CONTRACT_ASSERT( begin() <= end() );
|
||||
}) )
|
||||
|
||||
public:
|
||||
virtual ConstIter begin(void) const
|
||||
CONTRACT_FUNCTION( (class) (boundable)
|
||||
(public) (virtual) (ConstIter) (begin)( (void) ) (const)
|
||||
(body) (= 0;) )
|
||||
|
||||
virtual ConstIter end(void) const = 0;
|
||||
};
|
||||
|
||||
//]
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
46
example/myvector/main.cpp
Executable file
46
example/myvector/main.cpp
Executable file
@@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
#include "myvector.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << std::endl << "constructor()" << std::endl;
|
||||
myvector<double> v(3);
|
||||
const myvector<double>& cv = v; // A reference, no copy.
|
||||
|
||||
std::cout << std::endl << "copy constructor()" << std::endl;
|
||||
myvector<double> w(v);
|
||||
|
||||
std::cout << std::endl << "begin()" << std::endl;
|
||||
myvector<double>::iterator b = v.begin();
|
||||
std::cout << *b << std::endl;
|
||||
|
||||
std::cout << std::endl << "begin() const" << std::endl;
|
||||
myvector<double>::const_iterator cb = cv.begin();
|
||||
std::cout << *cb << std::endl;
|
||||
|
||||
std::cout << std::endl << "insert()" << std::endl;
|
||||
v.insert(b, 2, -3.21);
|
||||
|
||||
std::cout << std::endl << "operator[]" << std::endl;
|
||||
double v0 = v[0];
|
||||
std::cout << v0 << std::endl;
|
||||
|
||||
std::cout << std::endl << "push_back()" << std::endl;
|
||||
v.push_back(1.23);
|
||||
|
||||
std::cout << std::endl << "all_equals()" << std::endl;
|
||||
bool eq = myvector<double>::all_equals(v.begin(), v.end(), 1.23);
|
||||
std::cout << eq << std::endl; // It will be false.
|
||||
|
||||
std::cout << std::endl << "abs_total()" << std::endl;
|
||||
double tot = abs_total(v);
|
||||
std::cout << tot << std::endl;
|
||||
|
||||
std::cout << std::endl << "destructor()" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
27
example/myvector/main_nomacros.cpp
Executable file
27
example/myvector/main_nomacros.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
#include "myvector_nomacros.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << std::endl << "constructor()" << std::endl;
|
||||
myvector<double> v(3);
|
||||
|
||||
std::cout << std::endl << "push_back()" << std::endl;
|
||||
v.push_back(1.23);
|
||||
|
||||
std::cout << std::endl << "all_equals()" << std::endl;
|
||||
bool eq = myvector<double>::all_equals(v.begin(), v.end(), 1.23);
|
||||
std::cout << eq << std::endl; // It will be false.
|
||||
|
||||
std::cout << std::endl << "abs_total()" << std::endl;
|
||||
double tot = abs_total(v);
|
||||
std::cout << tot << std::endl;
|
||||
|
||||
std::cout << std::endl << "destructor()" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
245
example/myvector/myvector.hpp
Executable file
245
example/myvector/myvector.hpp
Executable file
@@ -0,0 +1,245 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
// Main documentation example that illustrates most library uses.
|
||||
|
||||
#ifndef MYVECTOR_HPP_
|
||||
#define MYVECTOR_HPP_
|
||||
|
||||
//[ myvector_cpp
|
||||
|
||||
// Base classes for subcontracting.
|
||||
#include "pushable.hpp"
|
||||
#include "boundable.hpp"
|
||||
#include "basic_begin.hpp"
|
||||
#include <contract.hpp> // This library.
|
||||
#include <boost/utility.hpp> // For `boost::prior()`.
|
||||
#include <vector> // STL vector.
|
||||
|
||||
// Wrapper that adds simple (not complete) contracts to C++ STL illustrating
|
||||
// most library usages. For simplicity, assume T is comparable and copyable.
|
||||
template<typename T>
|
||||
class myvector: public pushable<T>,
|
||||
public boundable<typename std::vector<T>::const_iterator>,
|
||||
private basic_begin<typename std::vector<T>::const_iterator> {
|
||||
|
||||
// Class invariants (checked by any function with a contract).
|
||||
CONTRACT_INVARIANT(
|
||||
(static)({ // Static invariants (optional).
|
||||
// Static class invariants `(static)({ ... })` are optional and they
|
||||
// could have been omitted since they assert nothing in this example.
|
||||
// When present, they can only access static members.
|
||||
}) ({ // Non-static invariants (can access object).
|
||||
CONTRACT_ASSERT( (size() == 0) == empty() );
|
||||
// More invariants here...
|
||||
}) )
|
||||
|
||||
public:
|
||||
typedef typename std::vector<T>::size_type size_type;
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
typedef typename std::vector<T>::const_reference const_reference;
|
||||
|
||||
// Contract for constructor.
|
||||
explicit myvector(size_type count): vector_(count)
|
||||
CONTRACT_CONSTRUCTOR( // Constructor contract macro.
|
||||
(class) (myvector) // Constructor signature.
|
||||
(public) (myvector)( (size_type)(count) )
|
||||
// Never object `this` in constructor preconditions.
|
||||
(postcondition) ({
|
||||
// Never `CONTRACT_OLDOF(this)` in constructor postconditions.
|
||||
CONTRACT_ASSERT( size() == count );
|
||||
})
|
||||
(body) ({
|
||||
// Do nothing in this case.
|
||||
}) )
|
||||
|
||||
// Contractor for overloaded member (resolved by argumnet name).
|
||||
myvector(const myvector& right)
|
||||
CONTRACT_CONSTRUCTOR( (class) (myvector)
|
||||
(public) (myvector)( (const myvector&)(right) )
|
||||
(postcondition) ({
|
||||
CONTRACT_ASSERT( vector_ == right.vector_ );
|
||||
})
|
||||
(body) (;) ) // Deferres body definition.
|
||||
|
||||
// Contract for destructor.
|
||||
virtual ~myvector(void)
|
||||
CONTRACT_DESTRUCTOR( // Destructor contract macro.
|
||||
(class) (myvector) // Destructor signature.
|
||||
// Must use `(void)` for no arguments.
|
||||
(public) (virtual) (myvector)( (void) )
|
||||
// No preconditions allowed (no arguments).
|
||||
// No postconditions allowed (no object after destructor).
|
||||
(body) (;) )
|
||||
|
||||
// Contract for member function.
|
||||
void insert(iterator where, size_type count, const T& element)
|
||||
CONTRACT_FUNCTION( // Function contract macro.
|
||||
(class) (copyable)(myvector) // Function signature.
|
||||
// Old values for object `this` and argument `where`.
|
||||
(public) (void) (insert)( (copyable)(iterator)(where)
|
||||
(size_type)(count) (const T&)(element) )
|
||||
(precondition) ({ // Function preconditions (optional).
|
||||
CONTRACT_ASSERT( (size() + count) <= max_size() );
|
||||
// More preconditions here...
|
||||
})
|
||||
(postcondition) ({ // Function postconditions (optional).
|
||||
// Any C++ code allowed in contracts (but keep it simple).
|
||||
// Old values of types tagged copyable via `CONTRACT_OLDOF()`.
|
||||
if (capacity() == CONTRACT_OLDOF(this)->capacity()) {
|
||||
CONTRACT_ASSERT( all_equals(
|
||||
boost::prior(CONTRACT_OLDOF(where)),
|
||||
boost::prior(CONTRACT_OLDOF(where)) + count,
|
||||
element) );
|
||||
}
|
||||
// More postconditions here...
|
||||
})
|
||||
(body) ({ // Function body (mandatory).
|
||||
vector_.insert(where, count, element);
|
||||
}) )
|
||||
|
||||
// Contract for constant member.
|
||||
const_iterator begin(void) const
|
||||
CONTRACT_FUNCTION( (class) (myvector)
|
||||
// Subcontracting for multiple inheritance.
|
||||
(inherit)(boundable<const_iterator>)
|
||||
(inherit)(basic_begin<const_iterator>)
|
||||
(public) (const_iterator) // Non-void result type.
|
||||
(begin)( (void) ) (const) // Constant.
|
||||
(postcondition) (result) ({ // Named result value.
|
||||
if (empty()) CONTRACT_ASSERT( result == end() );
|
||||
})
|
||||
(body) ({
|
||||
return vector_.begin();
|
||||
}) )
|
||||
|
||||
// Contract for overloaded member (resolved because not const).
|
||||
iterator begin(void)
|
||||
CONTRACT_FUNCTION( (class) (myvector) (public)
|
||||
(iterator) (begin)( (void) )
|
||||
(postcondition) (result) ({
|
||||
if (empty()) CONTRACT_ASSERT( result == end() );
|
||||
})
|
||||
(body) (
|
||||
;
|
||||
) )
|
||||
|
||||
// Contract for operator.
|
||||
const_reference operator[](size_type index) const
|
||||
CONTRACT_FUNCTION( (class) (myvector)
|
||||
// Must spell operator name also in words).
|
||||
(public) (const_reference) (operator([], at))(
|
||||
(size_type)(index) ) (const)
|
||||
(precondition) ({
|
||||
CONTRACT_ASSERT( index < size() );
|
||||
})
|
||||
(body) (;) )
|
||||
|
||||
// Main function example used in documentation.
|
||||
void push_back(const T& element)
|
||||
CONTRACT_FUNCTION(
|
||||
(class) (copyable)(myvector) (inherit)(pushable<T>)
|
||||
(public) (void) (push_back)( (const T&)(element) )
|
||||
(precondition) ({
|
||||
CONTRACT_ASSERT( size() < max_size() );
|
||||
})
|
||||
(postcondition) ({
|
||||
CONTRACT_ASSERT( size() == (CONTRACT_OLDOF(this)->size() + 1) );
|
||||
})
|
||||
(body) ({
|
||||
vector_.push_back(element);
|
||||
}) )
|
||||
|
||||
// Contract for template plus static member function.
|
||||
template<class Iter>
|
||||
static bool all_equals(Iter first, Iter last, const T& element)
|
||||
CONTRACT_FUNCTION( (class) (myvector)
|
||||
(public) (template)( (class)(Iter) ) // Function template.
|
||||
(static) (bool) (all_equals)( // Static member.
|
||||
(Iter)(first) (Iter)(last) (const T&)(element) )
|
||||
(precondition) ({
|
||||
CONTRACT_ASSERT( first < last );
|
||||
})
|
||||
(body) ({
|
||||
// For simplicity, let's assume T can be compared.
|
||||
for (Iter i = first; i < last; ++i) {
|
||||
if (*i != element) return false;
|
||||
}
|
||||
return true;
|
||||
}) )
|
||||
|
||||
// Similarly, complete contracts sketched here and add contracts
|
||||
// for all other functions (see [Crowl2006] vector example).
|
||||
bool empty(void) const { return vector_.empty(); }
|
||||
size_type size(void) const { return vector_.size(); }
|
||||
size_type max_size(void) const { return vector_.max_size(); }
|
||||
size_type capacity(void) const { return vector_.capacity(); }
|
||||
iterator end(void) { return vector_.end(); }
|
||||
const_iterator end(void) const { return vector_.end(); }
|
||||
const_reference back(void) const { return vector_.back(); }
|
||||
|
||||
private:
|
||||
std::vector<T> vector_;
|
||||
};
|
||||
|
||||
// Deferred constructor body definition.
|
||||
template<typename T>
|
||||
CONTRACT_CONSTRUCTOR_BODY(myvector<T>, myvector)(
|
||||
const myvector& right) {
|
||||
vector_ = right.vector_;
|
||||
}
|
||||
|
||||
// Deferred destructor body definition.
|
||||
template<typename T>
|
||||
CONTRACT_DESTRUCTOR_BODY(myvector<T>, myvector)(void) {
|
||||
// Do nothing in this case.
|
||||
}
|
||||
|
||||
// Deferred member function definition.
|
||||
template<typename T>
|
||||
typename myvector<T>::iterator myvector<T>::CONTRACT_BODY(begin)(
|
||||
void) {
|
||||
return vector_.begin();
|
||||
}
|
||||
|
||||
// Deferred member operator definition.
|
||||
template<typename T>
|
||||
typename myvector<T>::const_reference myvector<T>::
|
||||
CONTRACT_BODY(operator([], at))(
|
||||
size_type index) const {
|
||||
return vector_[index];
|
||||
}
|
||||
|
||||
// Contract for non-member function.
|
||||
double abs_total(const myvector<double>& vector)
|
||||
CONTRACT_FUNCTION(
|
||||
(double) (abs_total)( (const myvector<double>&)(vector) )
|
||||
(postcondition) (total) ({ // Result value named `total`.
|
||||
CONTRACT_ASSERT( total >= 0.0 );
|
||||
})
|
||||
(body) ({
|
||||
double total = 0.0;
|
||||
// Block invariants can appear anywhere in code block.
|
||||
CONTRACT_ASSERT_BLOCK_INVARIANT( total == 0.0 );
|
||||
|
||||
{ // Variant initialized locally to its loop.
|
||||
CONTRACT_INIT_LOOP_VARIANT;
|
||||
for (size_t i = 0; i < vector.size(); ++i) {
|
||||
// Block invariants used to assert loop invariants.
|
||||
CONTRACT_ASSERT_BLOCK_INVARIANT( i < vector.size() );
|
||||
// Loop variant (can only appear in loops).
|
||||
CONTRACT_ASSERT_LOOP_VARIANT( vector.size() - i );
|
||||
|
||||
total += vector[i];
|
||||
}
|
||||
}
|
||||
return total < 0.0 ? -total : total;
|
||||
}) )
|
||||
|
||||
//]
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
320
example/myvector/myvector_nomacros.hpp
Executable file
320
example/myvector/myvector_nomacros.hpp
Executable file
@@ -0,0 +1,320 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
// Main documentation example that illustrates contracts without the macros.
|
||||
|
||||
#ifndef MYVECTOR_NOMACROS_HPP_
|
||||
#define MYVECTOR_NOMACROS_HPP_
|
||||
|
||||
//[ myvector_nomacros_cpp
|
||||
|
||||
#include "pushable.hpp" // Base class for subcontracting.
|
||||
#include <contract.hpp> // This library.
|
||||
#include <vector> // STL vector.
|
||||
|
||||
// Wrapper that adds simple (not complete) contracts to C++ STL
|
||||
// without using the library contract macros.
|
||||
template<typename T>
|
||||
class myvector: public pushable<T> {
|
||||
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || /* Allow for */ \
|
||||
defined CONTRACT_CHECK_PRECONDITION || /* optional contract */ \
|
||||
defined CONTRACT_CHECK_POSTCONDITION /* compilation. */
|
||||
// Augmented state.
|
||||
friend class contract::state;
|
||||
mutable contract::state contract_state_;
|
||||
#endif // contracts
|
||||
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT
|
||||
// Static class invariants
|
||||
static void contract_static_invariant_(void) {
|
||||
// Assert nothing in this case.
|
||||
}
|
||||
// Class invariants.
|
||||
void contract_invariant_(void) const {
|
||||
if (!((size() == 0) == empty()))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
// More invariants here...
|
||||
}
|
||||
#endif // invariants
|
||||
|
||||
public:
|
||||
typedef typename std::vector<T>::size_type size_type;
|
||||
typedef typename std::vector<T>::const_reference const_reference;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
|
||||
// Contract for constructor.
|
||||
explicit myvector(size_type count): vector_(count)
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
{
|
||||
contract_contract_constructor_count_<0>().call(this, count);
|
||||
}
|
||||
private:
|
||||
#if defined CONTRACT_CHECK_PRECONDITION
|
||||
// Static preconditions (i.e., no object).
|
||||
static void contract_precondition_contract_constructor_count_(
|
||||
const size_type& count) /* no `const` (it is `static`) */ {
|
||||
}
|
||||
#endif // preconditions
|
||||
#if defined CONTRACT_CHECK_POSTCONDITION
|
||||
void contract_postcondition_contract_constructor_count_(
|
||||
contract::noold, // Always `noold` for old object.
|
||||
const size_type& count, contract::noold) const {
|
||||
if (!(size() == count))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
}
|
||||
#endif // postconditions
|
||||
protected:
|
||||
void contract_body_contract_constructor_(size_type count)
|
||||
#endif // contracts
|
||||
{
|
||||
// Do nothing in this case
|
||||
}
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
template<int ZERO>
|
||||
struct contract_contract_constructor_count_:
|
||||
contract::constructor< // Use `constructor` (not `function`).
|
||||
// Class type can never be tagged `copyable`.
|
||||
void (myvector*, size_type)> {
|
||||
contract_contract_constructor_count_(): contract::constructor <
|
||||
void (myvector*, size_type)
|
||||
>( &myvector::contract_body_contract_constructor_
|
||||
, &myvector::contract_precondition_contract_constructor_count_
|
||||
, &myvector::contract_postcondition_contract_constructor_count_
|
||||
) {}
|
||||
};
|
||||
public:
|
||||
#endif // contracts
|
||||
|
||||
// Contract for destructor.
|
||||
virtual ~myvector(void)
|
||||
// Destructors only check invariants.
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT
|
||||
{
|
||||
contract_contract_destructor_<0>().call(this);
|
||||
}
|
||||
protected:
|
||||
// No precondition and no postcondition functions.
|
||||
virtual void contract_body_contract_destructor_(void)
|
||||
#endif // invariant
|
||||
{
|
||||
// Do nothing in this case.
|
||||
}
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT
|
||||
template<int ZERO>
|
||||
struct contract_contract_destructor_:
|
||||
contract::destructor< // Use `destructor` (not `function`).
|
||||
// Class type can never be tagged `copyable`.
|
||||
void (myvector*)> {
|
||||
contract_contract_destructor_(): contract::destructor<
|
||||
void (myvector*)
|
||||
>(&myvector::contract_body_contract_destructor_ ) {}
|
||||
};
|
||||
public:
|
||||
#endif // invariant
|
||||
|
||||
// Contract for non-static member functions.
|
||||
void push_back(const T& element)
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
// Contracted function.
|
||||
{
|
||||
contract_push_back_element_<0>().call(this , element);
|
||||
}
|
||||
private: // Private so not to alter user call public API.
|
||||
#if defined CONTRACT_CHECK_PRECONDITION
|
||||
void contract_precondition_push_back_element_(const T& element) const {
|
||||
if (!(size() < max_size()))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
// More preconditions here...
|
||||
}
|
||||
#endif // preconditions
|
||||
#if defined CONTRACT_CHECK_POSTCONDITION
|
||||
void contract_postcondition_push_back_element_(
|
||||
const myvector* contract_old_this_, // Old value for object.
|
||||
const T& element, contract::noold // No old for element argument.
|
||||
) const {
|
||||
if (!(size() == (contract_old_this_->size() + 1)))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
// More postconditions here...
|
||||
}
|
||||
#endif // postconditions
|
||||
protected: // Must be protected (not private) to allow subcontracting.
|
||||
void contract_body_push_back_(const T& element)
|
||||
#endif // contracts
|
||||
// Original function definition (the body).
|
||||
{
|
||||
vector_.push_back(element);
|
||||
}
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
// Contract class.
|
||||
template<int ZERO>
|
||||
struct contract_push_back_element_: contract::nonstatic_member_function<
|
||||
// Function type for contracted function.
|
||||
// Copyable class type for old object value in postconditions.
|
||||
// For constant members, change `myvector` to `myvector const`.
|
||||
void (contract::copyable<myvector>*, const T&),
|
||||
// Base contract class for subcontracting.
|
||||
typename pushable<T>::template contract_push_back_element_<0>
|
||||
> {
|
||||
// Constructor specifies body, preconditions, and postconditions.
|
||||
contract_push_back_element_(): contract::nonstatic_member_function<
|
||||
void (contract::copyable<myvector>*, const T&),
|
||||
typename pushable<T>::template contract_push_back_element_<0>
|
||||
>( &myvector::contract_body_push_back_
|
||||
#if defined CONTRACT_CHECK_PRECONDITION
|
||||
, &myvector::contract_precondition_push_back_element_
|
||||
#endif // preconditions
|
||||
#if defined CONTRACT_CHECK_POSTCONDITION
|
||||
, &myvector::contract_postcondition_push_back_element_
|
||||
#endif // postconditions
|
||||
) {}
|
||||
};
|
||||
public: // Restore original access level.
|
||||
#endif // contracts
|
||||
|
||||
// Contract for template plus static member function.
|
||||
template<class Iter>
|
||||
static bool all_equals(Iter first, Iter last, const T& element)
|
||||
// Static members also check (static) class invariants.
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
{
|
||||
return contract_all_equals_first_last_element_<Iter>().call(
|
||||
first, last, element);
|
||||
}
|
||||
private:
|
||||
// Static template precondition and postcondition functions.
|
||||
#if defined CONTRACT_CHECK_PRECONDITION
|
||||
template<class Iter>
|
||||
static void contract_precondition_all_equals_first_last_element_(
|
||||
const Iter& first, const Iter& last, const T& element)
|
||||
/* no `const` */ {
|
||||
if (!(first < last))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
}
|
||||
#endif // preconditions
|
||||
#if defined CONTRACT_CHECK_POSTCONDITION
|
||||
template<class Iter>
|
||||
static void contract_postcondition_all_equals_first_last_element_(
|
||||
const Iter& first, contract::noold,
|
||||
const Iter& last, contract::noold,
|
||||
const T& element, contract::noold,
|
||||
const bool& result ) // Result value.
|
||||
/* no `const` */ {
|
||||
}
|
||||
#endif // postconditions
|
||||
protected:
|
||||
template<class Iter>
|
||||
static bool contract_body_all_equals_(
|
||||
Iter first, Iter last, const T& element)
|
||||
#endif // contracts
|
||||
{
|
||||
for (Iter i = first; i < last; ++i) {
|
||||
if (*i != element) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#if defined CONTRACT_CHECK_CLASS_INVARIANT || \
|
||||
defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
// Function template parameter `class Iter` already present so
|
||||
// no artificial `int ZERO` parameter.
|
||||
template<class Iter>
|
||||
struct contract_all_equals_first_last_element_: contract::static_member_function<
|
||||
bool (myvector*, Iter, Iter, const T&)
|
||||
> {
|
||||
contract_all_equals_first_last_element_(): contract:: static_member_function<
|
||||
bool (myvector*, Iter, Iter, const T&)
|
||||
>( &myvector::template contract_body_all_equals_<Iter>
|
||||
#if defined CONTRACT_CHECK_PRECONDITION
|
||||
, &myvector::template contract_precondition_all_equals_first_last_element_<Iter>
|
||||
#endif // preconditions
|
||||
#if defined CONTRACT_CHECK_POSTCONDITION
|
||||
, &myvector::template contract_postcondition_all_equals_first_last_element_<Iter>
|
||||
#endif // postconditions
|
||||
) {}
|
||||
};
|
||||
public:
|
||||
#endif // contracts
|
||||
|
||||
// Similarly, complete contracts sketched here and add contracts
|
||||
// for all other functions (see [Crowl2006] vector example).
|
||||
size_type size(void) const { return vector_.size(); }
|
||||
size_type max_size(void) const { return vector_.max_size(); }
|
||||
bool empty(void) const { return vector_.empty(); }
|
||||
const_reference back(void) const { return vector_.back(); }
|
||||
const_iterator begin(void) const { return vector_.begin(); }
|
||||
const_iterator end(void) const { return vector_.end(); }
|
||||
const_reference operator[](size_type index) const
|
||||
{ return vector_[index]; }
|
||||
|
||||
private:
|
||||
std::vector<T> vector_;
|
||||
};
|
||||
|
||||
// Contract for non-member function.
|
||||
double abs_total(const myvector<double>& vector)
|
||||
// Non-member members do not check invariants.
|
||||
#if defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
;
|
||||
void contract_precondition_abs_total_vector_(
|
||||
const myvector<double>& vector ) {
|
||||
}
|
||||
void contract_postcondition_abs_total_vector_(
|
||||
const myvector<double>& vector, contract::noold,
|
||||
const double& total) {
|
||||
if (!(total >= 0.0))
|
||||
throw contract::failure(__FILE__, __LINE__);
|
||||
}
|
||||
double contract_body_abs_total_(const myvector<double>& vector)
|
||||
#endif // preconditions or postconditions
|
||||
{
|
||||
double total = 0.0;
|
||||
CONTRACT_ASSERT_BLOCK_INVARIANT( total == 0.0 );
|
||||
{
|
||||
CONTRACT_INIT_LOOP_VARIANT;
|
||||
for (size_t i = 0; i < vector.size(); ++i) {
|
||||
CONTRACT_ASSERT_BLOCK_INVARIANT( i < vector.size() );
|
||||
CONTRACT_ASSERT_LOOP_VARIANT( vector.size() - i );
|
||||
|
||||
total += vector[i];
|
||||
}
|
||||
}
|
||||
return total < 0.0 ? -total : total;
|
||||
}
|
||||
#if defined CONTRACT_CHECK_PRECONDITION || \
|
||||
defined CONTRACT_CHECK_POSTCONDITION
|
||||
template<int ZERO>
|
||||
struct contract_abs_total_vector_: contract::nonmember_function<
|
||||
// Still use `function` but no class type, just use `(*)`.
|
||||
double (const myvector<double>&)
|
||||
> {
|
||||
contract_abs_total_vector_(): contract::nonmember_function<
|
||||
double (const myvector<double>&)>
|
||||
( &contract_body_abs_total_
|
||||
, &contract_precondition_abs_total_vector_
|
||||
, &contract_postcondition_abs_total_vector_
|
||||
) {}
|
||||
};
|
||||
// Contracted function defined last and `inline`.
|
||||
inline double abs_total(const myvector<double>& vector) {
|
||||
return contract_abs_total_vector_<0>().call(vector);
|
||||
}
|
||||
#endif // preconditions or postconditions
|
||||
|
||||
//]
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
38
example/myvector/pushable.hpp
Executable file
38
example/myvector/pushable.hpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2009-2010 Lorenzo Caminiti.
|
||||
// Use, modification, and distribution is subject to the
|
||||
// Contract++ Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt.)
|
||||
|
||||
// Base class for a myvector subcontracting example.
|
||||
|
||||
#ifndef PUSHABLE_HPP_
|
||||
#define PUSHABLE_HPP_
|
||||
|
||||
//[ pushable_cpp
|
||||
|
||||
#include <contract.hpp>
|
||||
|
||||
template<typename T>
|
||||
class pushable {
|
||||
|
||||
CONTRACT_INVARIANT( ({}) )
|
||||
|
||||
public:
|
||||
// Contract for pure virtual function.
|
||||
virtual void push_back(const T& element)
|
||||
CONTRACT_FUNCTION(
|
||||
(class) (pushable)
|
||||
(public) (virtual) (void) (push_back)( (const T&)(element) )
|
||||
(postcondition) ({
|
||||
CONTRACT_ASSERT( back() == element );
|
||||
})
|
||||
(body) (= 0;) ) // Pure virtual body.
|
||||
|
||||
virtual const T& back() const = 0;
|
||||
};
|
||||
|
||||
//]
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user