reviewed docs up to extra section. renamed DOXYGEN macro with BOOST_CONTRACT_DETAIL_DOXYGEN

This commit is contained in:
Lorenzo Caminiti
2017-08-02 22:45:45 -07:00
parent 2b73d42ee1
commit 024b5b9bc5
28 changed files with 840 additions and 702 deletions

View File

@@ -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);
//]

View File

@@ -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);

View File

@@ -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');

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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&,

View File

@@ -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);

View File

@@ -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 {};

View File

@@ -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)

View File

@@ -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());

View File

@@ -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);

View File

@@ -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_;
};

View File

@@ -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);
}
}
{