mirror of
https://github.com/boostorg/contract.git
synced 2026-02-26 04:32:22 +00:00
reviewed docs up to extra section. renamed DOXYGEN macro with BOOST_CONTRACT_DETAIL_DOXYGEN
This commit is contained in:
@@ -36,7 +36,7 @@ int main() {
|
||||
//]
|
||||
|
||||
//[check_macro
|
||||
// Implementation checks via macro (preferred).
|
||||
// Implementation checks via macro (disable run- and compile-time overhead).
|
||||
BOOST_CONTRACT_CHECK(gcd(12, 28) == 4);
|
||||
BOOST_CONTRACT_CHECK(gcd(4, 14) == 2);
|
||||
//]
|
||||
|
||||
@@ -12,8 +12,9 @@ int main() {
|
||||
int total = 10;
|
||||
|
||||
//[code_block
|
||||
{
|
||||
// Contract for a code block.
|
||||
/* ... */
|
||||
// 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([&] {
|
||||
@@ -25,7 +26,8 @@ int main() {
|
||||
;
|
||||
|
||||
total += v[0] + v[1] + v[2]; // Code block body.
|
||||
}
|
||||
} // Code block exit (check postconditions and exceptions guarantees).
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
assert(total == 16);
|
||||
|
||||
@@ -3,25 +3,9 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
//[friend_byte
|
||||
class bytes;
|
||||
|
||||
class byte {
|
||||
friend bool operator==(bytes const& left, byte const& right);
|
||||
|
||||
private:
|
||||
char value_;
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
public:
|
||||
// Could program invariants and contracts for following too.
|
||||
explicit byte(char value) : value_(value) {}
|
||||
bool empty() const { return value_ == '\0'; }
|
||||
};
|
||||
|
||||
//[friend_bytes
|
||||
class byte;
|
||||
|
||||
class bytes {
|
||||
// Friend functions are not member functions...
|
||||
friend bool operator==(bytes const& left, byte const& right) {
|
||||
@@ -51,6 +35,22 @@ public:
|
||||
bool empty() const { return values_ == ""; }
|
||||
};
|
||||
|
||||
//[friend_byte
|
||||
class byte {
|
||||
friend bool operator==(bytes const& left, byte const& right);
|
||||
|
||||
private:
|
||||
char value_;
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
public:
|
||||
// Could program invariants and contracts for following too.
|
||||
explicit byte(char value) : value_(value) {}
|
||||
bool empty() const { return value_ == '\0'; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
bytes p("aaa");
|
||||
byte a('a');
|
||||
|
||||
@@ -23,34 +23,43 @@
|
||||
#define CONTRACT_ASSERT_AXIOM(cond) BOOST_CONTRACT_ASSERT(true || (cond))
|
||||
|
||||
template<typename RandomIter, typename T>
|
||||
bool random_binary_search(RandomIter first, RandomIter last, T const& value) {
|
||||
RandomIter random_binary_search(RandomIter first, RandomIter last,
|
||||
T const& value) {
|
||||
RandomIter result;
|
||||
boost::contract::check c = boost::contract::function()
|
||||
.precondition([&] {
|
||||
BOOST_CONTRACT_ASSERT(first <= last);
|
||||
// Expensive O(n) assertion so marked "audit".
|
||||
CONTRACT_ASSERT_AUDIT(std::is_sorted(first, last));
|
||||
})
|
||||
.postcondition([&] {
|
||||
if(result != last) BOOST_CONTRACT_ASSERT(*result == value);
|
||||
})
|
||||
;
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
while(first < last) {
|
||||
RandomIter middle = first + ((last - first) >> 1);
|
||||
BOOST_CONTRACT_CHECK(*first <= *middle || value < *middle ||
|
||||
RandomIter being = first, end = last;
|
||||
while(begin < end) {
|
||||
RandomIter middle = begin + ((end - begin) >> 1);
|
||||
BOOST_CONTRACT_CHECK(*begin <= *middle || value < *middle ||
|
||||
*middle < value);
|
||||
|
||||
if(value < *middle) last = middle;
|
||||
else if(value > *middle) first = middle + 1;
|
||||
else return true;
|
||||
if(value < *middle) end = middle;
|
||||
else if(value > *middle) begin = middle + 1;
|
||||
else return result = middle;
|
||||
}
|
||||
return false;
|
||||
return result = last;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<char> i(3);
|
||||
i[0] = 'a'; i[1] = 'b'; i[2] = 'c';
|
||||
assert(random_binary_search(i.begin(), i.end(), 'b'));
|
||||
std::vector<char> v(3);
|
||||
v[0] = 'a'; v[1] = 'b'; v[2] = 'c';
|
||||
std::vector<char>::iterator i = random_binary_search(v.begin(), v.end(),
|
||||
'b');
|
||||
assert(i != v.end());
|
||||
assert(*i == 'b');
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <boost/contract.hpp>
|
||||
|
||||
void inc(int& x) {
|
||||
boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); // Old values.
|
||||
boost::contract::old_ptr<int> old_x = BOOST_CONTRACT_OLDOF(x); // Old value.
|
||||
boost::contract::check c = boost::contract::function()
|
||||
.precondition([&] {
|
||||
BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max()); // Line 17.
|
||||
|
||||
@@ -52,12 +52,12 @@ public:
|
||||
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
|
||||
#undef BASES
|
||||
|
||||
// BOOST_CONTRACT_OVERRIDE(_1) would generate reserved symbol `override__1`.
|
||||
// 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` type generated by NAMED_OVERRIDE macro above.
|
||||
// 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&,
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
//[old
|
||||
char replace(std::string& s, unsigned index, char x) {
|
||||
char result;
|
||||
boost::contract::old_ptr<char> old_y; // But old value copied later...
|
||||
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]); // Checked `index` in range.
|
||||
old_y = BOOST_CONTRACT_OLDOF(s[index]);
|
||||
})
|
||||
.postcondition([&] {
|
||||
BOOST_CONTRACT_ASSERT(s[index] == x);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <cassert>
|
||||
|
||||
//[old_if_copyable_offset
|
||||
template<typename T>
|
||||
template<typename T> // T might or might not be copyable.
|
||||
void offset(T& x, int count) {
|
||||
// No compiler error if T has no copy constructor...
|
||||
boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x);
|
||||
@@ -29,7 +29,7 @@ void offset(T& x, int count) {
|
||||
// Copyable type but...
|
||||
class w {
|
||||
public:
|
||||
w(w const&) { /* Some very expensive copy here operation... */ }
|
||||
w(w const&) { /* Some very expensive copy here operation here... */ }
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
@@ -87,11 +87,11 @@ namespace boost { namespace contract {
|
||||
//]
|
||||
|
||||
//[old_if_copyable_n_decl
|
||||
// Non-copyable type so...
|
||||
class n {
|
||||
class n { // Do not want to use boost::noncopyable but...
|
||||
int num_;
|
||||
|
||||
n(n const&); // Unimplemented private copy constructor (not copyable).
|
||||
private:
|
||||
n(n const&); // ...unimplemented private copy constructor (so non-copyable).
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
};
|
||||
|
||||
//[old_if_copyable_n_spec
|
||||
// ...specialize `boost::is_copy_constructible` (no need for this on C++11).
|
||||
// Specialize `boost::is_copy_constructible` (no need for this on C++11).
|
||||
namespace boost { namespace contract {
|
||||
template<>
|
||||
struct is_old_value_copyable<n> : boost::false_type {};
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
|
||||
//[private_protected
|
||||
class counter {
|
||||
// Private and protected functions use `function()` (like non-members).
|
||||
protected:
|
||||
virtual void set(int n, boost::contract::virtual_* = 0) {
|
||||
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);
|
||||
@@ -25,7 +24,7 @@ protected:
|
||||
n_ = n;
|
||||
}
|
||||
|
||||
private:
|
||||
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()
|
||||
@@ -47,7 +46,7 @@ private:
|
||||
//]
|
||||
|
||||
public:
|
||||
virtual int get(boost::contract::virtual_* v = 0) const {
|
||||
int get() const {
|
||||
int result;
|
||||
boost::contract::check c = boost::contract::public_function(
|
||||
v, result, this)
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
//[private_protected_virtual_counter
|
||||
class counter {
|
||||
// Virtual private and protected functions still declare extra
|
||||
// `virtual_* = 0` parameter (otherwise they cannot be overridden).
|
||||
// `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()
|
||||
boost::contract::check c = boost::contract::function() // ...no `v`.
|
||||
.precondition([&] {
|
||||
BOOST_CONTRACT_ASSERT(n <= 0);
|
||||
})
|
||||
@@ -28,8 +28,8 @@ protected:
|
||||
|
||||
private:
|
||||
virtual void dec(boost::contract::virtual_* = 0) {
|
||||
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get());
|
||||
boost::contract::check c = boost::contract::function()
|
||||
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());
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
//[public_virtual_function
|
||||
public:
|
||||
// Contract for a public virtual function (but no override).
|
||||
virtual int push_back(int id, boost::contract::virtual_* v = 0) {
|
||||
virtual int push_back(int id, boost::contract::virtual_* v = 0) { // Extra `v`.
|
||||
int result;
|
||||
boost::contract::old_ptr<bool> old_find =
|
||||
BOOST_CONTRACT_OLDOF(v, find(id)); // Pass `v`.
|
||||
@@ -84,8 +84,7 @@ public:
|
||||
boost::contract::check c = boost::contract::public_function(
|
||||
v, result, this) // Pass `v` and `result`.
|
||||
.precondition([&] {
|
||||
// Specified identifier must not already be in container.
|
||||
BOOST_CONTRACT_ASSERT(!find(id));
|
||||
BOOST_CONTRACT_ASSERT(!find(id)); // ID cannot be already present.
|
||||
})
|
||||
.postcondition([&] (int const result) {
|
||||
if(!*old_find) {
|
||||
@@ -136,8 +135,7 @@ public:
|
||||
override_push_back // Pass override plus below function pointer...
|
||||
>(v, result, &identifiers::push_back, this, id) // ...and arguments.
|
||||
.precondition([&] { // Check in OR with bases.
|
||||
// Do nothing if specified identifier already in container.
|
||||
BOOST_CONTRACT_ASSERT(find(id));
|
||||
BOOST_CONTRACT_ASSERT(find(id)); // ID can be already present.
|
||||
})
|
||||
.postcondition([&] (int const result) { // Check in AND with bases.
|
||||
if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size);
|
||||
|
||||
@@ -8,40 +8,40 @@
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
//[pure_virtual_public_base
|
||||
//[pure_virtual_public_base_begin
|
||||
template<typename Iterator>
|
||||
class range {
|
||||
public:
|
||||
// Pure virtual function declaration (contract not here, below instead).
|
||||
// Pure virtual function declaration (contract in definition below).
|
||||
virtual Iterator begin(boost::contract::virtual_* v = 0) = 0;
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
// Could program class invariants and contracts for the following too.
|
||||
virtual Iterator end() = 0;
|
||||
virtual bool empty() const = 0;
|
||||
};
|
||||
|
||||
//[pure_virtual_public_impl
|
||||
//[pure_virtual_public_base_end
|
||||
/* ... */
|
||||
};
|
||||
//]
|
||||
|
||||
//[pure_virtual_public_base_impl
|
||||
// Pure virtual function default implementation (out-of-line in C++).
|
||||
template<typename Iterator>
|
||||
Iterator range<Iterator>::begin(boost::contract::virtual_* v) {
|
||||
Iterator result;
|
||||
// Pass `result` right after `v`...
|
||||
Iterator result; // As usual, virtual pass `result` right after `v`...
|
||||
boost::contract::check c = boost::contract::public_function(v, result, this)
|
||||
// ...plus postconditions take `result` as parameter (not capture).
|
||||
.postcondition([&] (Iterator const& result) {
|
||||
if(empty()) BOOST_CONTRACT_ASSERT(result == end());
|
||||
})
|
||||
;
|
||||
|
||||
assert(false); // Pure function body never executed by this library.
|
||||
// Pure function body (never executed by this library).
|
||||
assert(false);
|
||||
return result;
|
||||
}
|
||||
//]
|
||||
|
||||
//[pure_virtual_public_derived
|
||||
template<typename T>
|
||||
class vector
|
||||
#define BASES public range<typename std::vector<T>::iterator>
|
||||
@@ -65,9 +65,7 @@ public:
|
||||
|
||||
return result = vect_.begin();
|
||||
}
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
BOOST_CONTRACT_OVERRIDE(begin)
|
||||
|
||||
// Could program class invariants and contracts for the following too.
|
||||
iterator end() { return vect_.end(); }
|
||||
@@ -75,8 +73,6 @@ public:
|
||||
T const& front() const { return vect_.front(); }
|
||||
void push_back(T const& value) { vect_.push_back(value); }
|
||||
|
||||
BOOST_CONTRACT_OVERRIDE(begin)
|
||||
|
||||
private:
|
||||
std::vector<T> vect_;
|
||||
};
|
||||
|
||||
@@ -270,8 +270,8 @@ public:
|
||||
postcondition {
|
||||
size() == count;
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
if(count > oldof size()) {
|
||||
boost::algorithm::all_of_equal(begin() + oldof size(),
|
||||
if(count > oldof(size())) {
|
||||
boost::algorithm::all_of_equal(begin() + oldof(size()),
|
||||
end(), value);
|
||||
}
|
||||
}
|
||||
@@ -401,8 +401,8 @@ public:
|
||||
size() < max_size();
|
||||
}
|
||||
postcondition {
|
||||
size() == oldof size() + 1;
|
||||
capacity() >= oldof capacity()
|
||||
size() == oldof(size()) + 1;
|
||||
capacity() >= oldof(capacity())
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
back() == value;
|
||||
}
|
||||
@@ -425,7 +425,7 @@ public:
|
||||
!empty();
|
||||
}
|
||||
postcondition {
|
||||
size() == oldof size() - 1;
|
||||
size() == oldof(size()) - 1;
|
||||
}
|
||||
{
|
||||
vect_.pop_back();
|
||||
@@ -471,12 +471,12 @@ public:
|
||||
size() < max_size();
|
||||
}
|
||||
postcondition(result) {
|
||||
size() == oldof size() + 1;
|
||||
capacity() >= oldof capacity();
|
||||
size() == oldof(size()) + 1;
|
||||
capacity() >= oldof(capacity());
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
*result == value;
|
||||
}
|
||||
// if(capacity() > oldof capacity())
|
||||
// if(capacity() > oldof(capacity()))
|
||||
// [begin(), end()) is invalid
|
||||
// else
|
||||
// [where, end()) is invalid
|
||||
@@ -500,12 +500,12 @@ public:
|
||||
size() + count < max_size();
|
||||
}
|
||||
postcondition {
|
||||
size() == oldof size() + count;
|
||||
capacity() >= oldof capacity();
|
||||
size() == oldof(size()) + count;
|
||||
capacity() >= oldof(capacity());
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
if(capacity() == oldof capacity()) {
|
||||
boost::algorithm::all_of_equal(boost::prior(oldof where),
|
||||
boost::prior(oldof where) + count, value);
|
||||
if(capacity() == oldof(capacity())) {
|
||||
boost::algorithm::all_of_equal(boost::prior(oldof(where)),
|
||||
boost::prior(oldof(where)) + count, value);
|
||||
}
|
||||
// [where, end()) is invalid
|
||||
}
|
||||
@@ -535,12 +535,12 @@ public:
|
||||
// [first, last) is not contained in [begin(), end())
|
||||
}
|
||||
postcondition {
|
||||
size() == oldof size() + std::distance(first, last);
|
||||
capacity() >= oldof capacity();
|
||||
size() == oldof(size()) + std::distance(first, last);
|
||||
capacity() >= oldof(capacity());
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
if(capacity() == oldof capacity()) {
|
||||
boost::algorithm::all_of_equal(boost::prior(oldof where),
|
||||
boost::prior(oldof where) + count, value);
|
||||
if(capacity() == oldof(capacity())) {
|
||||
boost::algorithm::all_of_equal(boost::prior(oldof(where)),
|
||||
boost::prior(oldof(where)) + count, value);
|
||||
}
|
||||
// [where, end()) is invalid
|
||||
}
|
||||
@@ -589,7 +589,7 @@ public:
|
||||
size() >= std::distance(first, lasst);
|
||||
}
|
||||
postcondition(result) {
|
||||
size() == oldof size() - std::distance(first, last);
|
||||
size() == oldof(size()) - std::distance(first, last);
|
||||
if(empty()) result == end();
|
||||
// [first, last) is invalid
|
||||
}
|
||||
@@ -619,8 +619,8 @@ public:
|
||||
}
|
||||
postcondition {
|
||||
if constexpr(boost::has_equal_to<T>::value) {
|
||||
*this == oldof other;
|
||||
other == oldof *this;
|
||||
*this == oldof(other);
|
||||
other == oldof(*this);
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user