1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
#include <vector>
#include <limits>
#include <cassert>
//[ifdef_macro_function
// Use macro interface to completely disable contract code compilation.
#include <boost/contract_macro.hpp>
int inc(int& x) {
int result;
BOOST_CONTRACT_OLD_PTR(int)(old_x, x);
BOOST_CONTRACT_FUNCTION()
BOOST_CONTRACT_PRECONDITION([&] {
BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max());
})
BOOST_CONTRACT_POSTCONDITION([&] {
BOOST_CONTRACT_ASSERT(x == *old_x + 1);
BOOST_CONTRACT_ASSERT(result == *old_x);
})
;
return result = x++;
}
//]
template<typename T>
class pushable {
friend class boost::contract::access; // Left in code (almost no overhead).
BOOST_CONTRACT_INVARIANT({
BOOST_CONTRACT_ASSERT(capacity() <= max_size());
})
public:
virtual void push_back(
T const& x,
boost::contract::virtual_* v = 0 // Left in code (almost no overhead).
) = 0;
protected:
virtual unsigned capacity() const = 0;
virtual unsigned max_size() const = 0;
};
template<typename T>
void pushable<T>::push_back(T const& x, boost::contract::virtual_* v) {
BOOST_CONTRACT_OLD_PTR(unsigned)(v, old_capacity, capacity());
BOOST_CONTRACT_PUBLIC_FUNCTION(v, this)
BOOST_CONTRACT_PRECONDITION([&] {
BOOST_CONTRACT_ASSERT(capacity() < max_size());
})
BOOST_CONTRACT_POSTCONDITION([&] {
BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity);
})
;
assert(false); // Shall never execute this body.
}
//[ifdef_macro_class
class integers
#define BASES public pushable<int>
:
// Left in code (almost no overhead).
private boost::contract::constructor_precondition<integers>,
BASES
{
// Followings left in code (almost no overhead).
friend class boost::contract::access;
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
BOOST_CONTRACT_INVARIANT({
BOOST_CONTRACT_ASSERT(size() <= capacity());
})
public:
integers(int from, int to) :
BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(integers)([&] {
BOOST_CONTRACT_ASSERT(from <= to);
}),
vect_(to - from + 1)
{
BOOST_CONTRACT_CONSTRUCTOR(this)
BOOST_CONTRACT_POSTCONDITION([&] {
BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1));
})
;
for(int x = from; x <= to; ++x) vect_.at(x - from) = x;
}
virtual ~integers() {
BOOST_CONTRACT_DESTRUCTOR(this); // Check invariants.
}
virtual void push_back(
int const& x,
boost::contract::virtual_* v = 0 // Left in code (almost no overhead).
) /* override */ {
BOOST_CONTRACT_OLD_PTR(unsigned)(old_size);
BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_push_back)(
v, &integers::push_back, this, x)
BOOST_CONTRACT_PRECONDITION([&] {
BOOST_CONTRACT_ASSERT(size() < max_size());
})
BOOST_CONTRACT_OLD([&] {
old_size = BOOST_CONTRACT_OLDOF(v, size());
})
BOOST_CONTRACT_POSTCONDITION([&] {
BOOST_CONTRACT_ASSERT(size() == *old_size + 1);
})
BOOST_CONTRACT_EXCEPT([&] {
BOOST_CONTRACT_ASSERT(size() == *old_size);
})
;
vect_.push_back(x);
}
private:
BOOST_CONTRACT_OVERRIDE(push_back) // Left in code (almost no overhead).
/* ... */
//]
public: // Could program contracts for these too...
unsigned size() const { return vect_.size(); }
unsigned max_size() const { return vect_.max_size(); }
unsigned capacity() const { return vect_.capacity(); }
private:
std::vector<int> vect_;
};
int main() {
integers i(1, 10);
int x = 123;
i.push_back(inc(x));
assert(x == 124);
assert(i.size() == 11);
return 0;
}
|