2 // Copyright (C) 2008-2018 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0 (see accompanying
4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
7 #include <boost/contract.hpp>
13 class unique_identifiers :
14 private boost::contract::constructor_precondition<unique_identifiers>
17 void invariant() const {
18 BOOST_CONTRACT_ASSERT(size() >= 0);
24 // Contract for a constructor.
25 unique_identifiers(int from, int to) :
26 boost::contract::constructor_precondition<unique_identifiers>([&] {
27 BOOST_CONTRACT_ASSERT(from >= 0);
28 BOOST_CONTRACT_ASSERT(to >= from);
31 boost::contract::check c = boost::contract::constructor(this)
33 BOOST_CONTRACT_ASSERT(size() == (to - from + 1));
38 for(int id = from; id <= to; ++id) vect_.push_back(id);
44 // Contract for a destructor.
45 virtual ~unique_identifiers() {
46 // Following contract checks class invariants.
47 boost::contract::check c = boost::contract::destructor(this);
49 // Destructor body here... (do nothing in this example).
54 // Following contract checks invariants.
55 boost::contract::check c = boost::contract::public_function(this);
61 // Contract for a public function (but no static, virtual, or override).
62 bool find(int id) const {
64 boost::contract::check c = boost::contract::public_function(this)
66 BOOST_CONTRACT_ASSERT(id >= 0);
69 if(size() == 0) BOOST_CONTRACT_ASSERT(!result);
74 return result = std::find(vect_.begin(), vect_.end(), id) !=
79 //[public_virtual_function
81 // Contract for a public virtual function (but no override).
82 virtual int push_back(int id, boost::contract::virtual_* v = 0) { // Extra `v`.
84 boost::contract::old_ptr<bool> old_find =
85 BOOST_CONTRACT_OLDOF(v, find(id)); // Pass `v`.
86 boost::contract::old_ptr<int> old_size =
87 BOOST_CONTRACT_OLDOF(v, size()); // Pass `v`.
88 boost::contract::check c = boost::contract::public_function(
89 v, result, this) // Pass `v` and `result`.
91 BOOST_CONTRACT_ASSERT(id >= 0);
92 BOOST_CONTRACT_ASSERT(!find(id)); // ID cannot be already present.
94 .postcondition([&] (int const result) {
96 BOOST_CONTRACT_ASSERT(find(id));
97 BOOST_CONTRACT_ASSERT(size() == *old_size + 1);
99 BOOST_CONTRACT_ASSERT(result == id);
110 std::vector<int> vect_;
116 //[public_derived_class_begin
118 #define BASES public unique_identifiers
122 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Bases typedef.
125 void invariant() const { // Check in AND with bases.
126 BOOST_CONTRACT_ASSERT(empty() == (size() == 0));
130 //[public_function_override
132 // Contract for a public function override.
133 int push_back(int id, boost::contract::virtual_* v = 0) /* override */ {
135 boost::contract::old_ptr<bool> old_find =
136 BOOST_CONTRACT_OLDOF(v, find(id));
137 boost::contract::old_ptr<int> old_size =
138 BOOST_CONTRACT_OLDOF(v, size());
139 boost::contract::check c = boost::contract::public_function<
140 override_push_back // Pass override type plus below function pointer...
141 >(v, result, &identifiers::push_back, this, id) // ...and arguments.
142 .precondition([&] { // Check in OR with bases.
143 BOOST_CONTRACT_ASSERT(id >= 0);
144 BOOST_CONTRACT_ASSERT(find(id)); // ID can be already present.
146 .postcondition([&] (int const result) { // Check in AND with bases.
147 if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size);
152 if(!find(id)) unique_identifiers::push_back(id); // Else, do nothing.
155 BOOST_CONTRACT_OVERRIDE(push_back) // Define `override_push_back`.
159 // Following contract checks invariants.
160 boost::contract::check c = boost::contract::public_function(this);
164 identifiers(int from, int to) : unique_identifiers(from, to) {
165 // Following contract checks invariants.
166 boost::contract::check c = boost::contract::constructor(this);
169 //[public_derived_class_end
175 unique_identifiers uids(1, 4);
176 assert(uids.find(2));
177 assert(!uids.find(5));
179 assert(uids.find(5));
181 identifiers ids(10, 40);
182 assert(!ids.find(50));
185 assert(ids.find(50));