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
|
// 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 <boost/contract.hpp>
#include <limits>
#include <cassert>
//[private_protected_virtual_counter
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_;
/* ... */
//]
public:
virtual int get(boost::contract::virtual_* v = 0) const {
int result;
boost::contract::check c = boost::contract::public_function(
v, result, this)
.postcondition([&] (int const result) {
BOOST_CONTRACT_ASSERT(result <= 0);
BOOST_CONTRACT_ASSERT(result == n_);
})
;
return result = n_;
}
counter() : n_(0) {} // Should contract constructor and destructor too.
void invariant() const {
BOOST_CONTRACT_ASSERT(get() <= 0);
}
friend int main();
};
//[private_protected_virtual_counter10
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);
}
/* ... */
//]
virtual int get(boost::contract::virtual_* v = 0) const {
int result;
boost::contract::check c = boost::contract::public_function<
override_get>(v, result, &counter10::get, this);
return result = counter::get();
}
BOOST_CONTRACT_OVERRIDE(get)
// Should contract default constructor and destructor too.
void invariant() const {
BOOST_CONTRACT_ASSERT(get() % 10 == 0);
}
};
int main() {
counter cnt;
assert(cnt.get() == 0);
cnt.dec();
assert(cnt.get() == -1);
counter10 cnt10;
counter& b = cnt10; // Polymorphic calls.
assert(b.get() == 0);
b.dec();
assert(b.get() == -10);
return 0;
}
|