finished all docs up to reference section

This commit is contained in:
Lorenzo Caminiti
2017-02-26 09:23:01 -08:00
parent 2dc0038b14
commit 6df8cb1d29
48 changed files with 1917 additions and 1020 deletions

View File

@@ -11,8 +11,9 @@ test-suite features :
[ subdir-run features : introduction ]
[ subdir-run features : introduction_comments ]
[ subdir-run features : function ]
[ subdir-run features : lambda_function ]
[ subdir-run features : non_member ]
[ subdir-run features : lambda ]
[ subdir-run features : loop ]
[ subdir-run features : code_block ]
[ subdir-run features : public ]
[ subdir-run features : base_types ]
@@ -22,8 +23,11 @@ test-suite features :
[ subdir-run features : private_protected_virtual_multi ]
[ subdir-run features : check ]
[ subdir-run features : friend ]
[ subdir-run features : friend_invariant ]
[ subdir-run features : old ]
[ subdir-run features : optional_result ]
[ subdir-run features : optional_result_virtual ]
[ subdir-run features : pure_virtual_public ]
[ subdir-run features : overload ]
[ subdir-run features : named_override ]
@@ -39,8 +43,8 @@ test-suite features :
[ subdir-run features : throw_on_failure ]
[ subdir-run features : ifdef ]
[ subdir-run features : ifdef_macro ]
[ subdir-run features : base_types_no_macros ]
[ subdir-run features : old_no_macros ]
[ subdir-run features : base_types_no_macro ]
[ subdir-run features : old_no_macro ]
[ subdir-run features : no_lambdas ]
[ subdir-run features : no_lambdas_local_func ]
;

View File

@@ -53,7 +53,7 @@ private:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // ...private bases.
#undef BASES
BOOST_CONTRACT_OVERRIDE(push_back) // ..private overrides.
BOOST_CONTRACT_OVERRIDE(push_back) // ...private overrides.
void invariant() const { // ...private invariants.
BOOST_CONTRACT_ASSERT(size() <= capacity());

View File

@@ -112,7 +112,7 @@ private:
std::vector<char> vect_;
};
//[base_types_no_macros
//[base_types_no_macro
#include <boost/mpl/vector.hpp>
class chars :

View File

@@ -40,7 +40,7 @@ struct is_input_iterator : std::is_same<
//[call_if_cxx14
template<typename Iter, typename Dist>
void myadvance(Iter& i, Dist n) {
Iter *p = &i; // So captures change actual pointed iterator value.
Iter* p = &i; // So captures change actual pointed iterator value.
boost::contract::call_if<is_random_access_iterator<Iter> >(
std::bind([] (auto p, auto n) { // C++14 generic lambda.
*p += n;

View File

@@ -5,7 +5,6 @@
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
#include <boost/contract.hpp>
#include <cassert>
int gcd(int const a, int const b) {
int result;
@@ -20,32 +19,28 @@ int gcd(int const a, int const b) {
})
;
// Function body follows...
//[check_class
int x = a, y = b;
boost::contract::check c1 = [&] { // Body checks with functor.
BOOST_CONTRACT_ASSERT(x == a);
BOOST_CONTRACT_ASSERT(y == b);
};
//]
//[check_macro
while(x != y) {
BOOST_CONTRACT_CHECK(x > 0); // Body checks with macros (preferred).
BOOST_CONTRACT_CHECK(y > 0);
if(x > y) x = x - y;
else y = y - x;
}
//]
return result = x;
}
int main() {
assert(gcd(12, 28) == 4);
assert(gcd(4, 14) == 2);
//[check_class
boost::contract::check c = [&] { // Implementation checks via functor.
BOOST_CONTRACT_ASSERT(gcd(12, 28) == 4);
BOOST_CONTRACT_ASSERT(gcd(4, 14) == 2);
};
//]
//[check_macro
// Implementation checks via macro (preferred).
BOOST_CONTRACT_CHECK(gcd(12, 28) == 4);
BOOST_CONTRACT_CHECK(gcd(4, 14) == 2);
//]
return 0;
}

View File

@@ -12,7 +12,8 @@ int main() {
int total = 10;
//[code_block
{ // Contract for a code block (also for-loop, while-loop, etc.).
{
// Contract for a code block.
boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLD(total);
boost::contract::check c = boost::contract::function()
.precondition([&] {
@@ -23,7 +24,7 @@ int main() {
})
;
total += v[0] + v[1] + v[2]; // Body.
total += v[0] + v[1] + v[2]; // Code block body.
}
//]

View File

@@ -0,0 +1,62 @@
#include <boost/contract.hpp>
#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 bytes {
// Friend functions are not member functions...
friend bool operator==(bytes const& left, byte const& right) {
// ...so check contracts via `function` (which won't check invariants).
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(!left.empty());
BOOST_CONTRACT_ASSERT(!right.empty());
})
;
for(char const* x = left.values_.c_str(); *x != '\0'; ++x) {
if(*x != right.value_) return false;
}
return true;
}
private:
std::string values_;
/* ... */
//]
public:
// Could program invariants and contracts for following too.
explicit bytes(std::string const& values) : values_(values) {}
bool empty() const { return values_ == ""; }
};
int main() {
bytes p("aaa");
byte a('a');
assert(p == a);
bytes q("aba");
assert(!(q == a)); // No operator!=.
return 0;
}

View File

@@ -0,0 +1,54 @@
#include <boost/contract.hpp>
#include <cassert>
//[friend_invariant
template<typename T>
class positive {
public:
void invariant() const {
BOOST_CONTRACT_ASSERT(value() > 0);
}
// Can be considered an extension of enclosing class' public interface...
friend void swap(positive& object, T& value) {
boost::contract::old_ptr<T> old_object_value =
BOOST_CONTRACT_OLDOF(object.value());
boost::contract::old_ptr<T> old_value = BOOST_CONTRACT_OLDOF(value);
// ...so it can be made to check invariants via `public_function`.
boost::contract::check c = boost::contract::public_function(&object)
.precondition([&] {
BOOST_CONTRACT_ASSERT(value > 0);
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(object.value() == *old_value);
BOOST_CONTRACT_ASSERT(value == *old_object_value);
})
;
T saved = object.value_;
object.value_ = value;
value = saved;
}
private:
T value_;
/* ... */
//]
public:
// Could program contracts for following too.
explicit positive(T const& value) : value_(value) {}
T value() const { return value_; }
};
int main() {
positive<int> i(123);
int x = 456;
swap(i, x);
assert(i.value() == 456);
assert(x == 123);
return 0;
}

View File

@@ -10,6 +10,7 @@
//[ifdef_function
// Use #ifdef to selectively disable contract compilation.
#include <boost/contract/core/config.hpp>
#ifndef BOOST_CONTRACT_NO_ALL
#include <boost/contract.hpp>
#endif

View File

@@ -31,7 +31,7 @@ int inc(int& x) {
template<typename T>
class pushable {
friend class boost::contract::access; // OK if this always left in code.
friend class boost::contract::access; // Almost no overhead, always in code.
BOOST_CONTRACT_INVARIANT({
BOOST_CONTRACT_ASSERT(capacity() <= max_size());
@@ -40,7 +40,7 @@ class pushable {
public:
virtual void push_back(
T const& x,
boost::contract::virtual_* v = 0 // OK if this always left in code.
boost::contract::virtual_* v = 0 // Almost no overhead, always in code.
) = 0;
protected:
@@ -66,11 +66,11 @@ void pushable<T>::push_back(T const& x, boost::contract::virtual_* v) {
class integers
#define BASES public pushable<int>
:
// OK if following extra base class always left in code.
// Almost no overhead for this extra base, always in code.
private boost::contract::constructor_precondition<integers>,
BASES
{
// OK if followings always left in code.
// Almost no overhead for followings, always in code.
friend class boost::contract::access;
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
@@ -122,7 +122,7 @@ public:
}
private:
BOOST_CONTRACT_OVERRIDE(push_back) // OK if always left in code.
BOOST_CONTRACT_OVERRIDE(push_back) // About no overhead, always in code.
/* ... */
//]

View File

@@ -10,11 +10,11 @@ int main() {
v.push_back(2);
v.push_back(3);
//[lambda_function
//[lambda
int total = 0;
std::for_each(v.cbegin(), v.cend(),
// Contract for a lambda function.
[&total] (int const x) {
// Contract for a lambda function.
boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLD(total);
boost::contract::check c = boost::contract::function()
.precondition([&] {

35
example/features/loop.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include <boost/contract.hpp>
#include <vector>
#include <algorithm>
#include <limits>
int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
//[loop
int total = 0;
for(std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
// Contract for a for-loop (same for while- and all other loops).
boost::contract::old_ptr<int> old_total = BOOST_CONTRACT_OLD(total);
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(
total + *i <= std::numeric_limits<int>::max());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(total == *old_total + *i);
})
;
total += *i; // For-loop body.
}
//]
assert(total == 6);
return 0;
}

View File

@@ -17,8 +17,59 @@ public:
if(!moved()) { // Do not check (some) invariants for moved-from objects.
BOOST_CONTRACT_ASSERT(index() < size());
}
// More invariants here (that must hold also for moved-from objects).
}
// Move constructor.
/* implicit */ circular_buffer(circular_buffer&& other) :
boost::contract::constructor_precondition<circular_buffer>([&] {
BOOST_CONTRACT_ASSERT(!other.moved());
})
{
boost::contract::check c = boost::contract::constructor(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(!moved());
BOOST_CONTRACT_ASSERT(other.moved());
})
;
move(std::forward<circular_buffer>(other));
}
// Move assignment.
circular_buffer& operator=(circular_buffer&& other) {
// Moved-from can be (move) assigned (so no pre `!moved()` here).
boost::contract::check c = boost::contract::public_function(this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(!other.moved());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(!moved());
BOOST_CONTRACT_ASSERT(other.moved());
})
;
return move(std::forward<circular_buffer>(other));
}
~circular_buffer() {
// Moved-from can always be destroyed (in fact no preconditions).
boost::contract::check c = boost::contract::destructor(this);
}
bool moved() const {
boost::contract::check c = boost::contract::public_function(this);
return moved_;
}
private:
bool moved_;
/* ... */
//]
public:
explicit circular_buffer(std::vector<char> const& data,
unsigned start = 0) :
boost::contract::constructor_precondition<circular_buffer>([&] {
@@ -35,11 +86,6 @@ public:
;
}
~circular_buffer() {
// Moved-from can always be destroyed (so no pre `!moved()` here).
boost::contract::check c = boost::contract::destructor(this);
}
// Copy constructor.
/* implicit */ circular_buffer(circular_buffer const& other) :
boost::contract::constructor_precondition<circular_buffer>([&] {
@@ -70,38 +116,6 @@ public:
return copy(other);
}
// Move constructor.
/* implicit */ circular_buffer(circular_buffer&& other) :
boost::contract::constructor_precondition<circular_buffer>([&] {
BOOST_CONTRACT_ASSERT(!other.moved());
})
{
boost::contract::check c = boost::contract::constructor(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(!moved());
BOOST_CONTRACT_ASSERT(other.moved());
})
;
move(std::forward<circular_buffer>(other));
}
// Move assignment.
circular_buffer& operator=(circular_buffer&& other) {
// Moved-from can be (move) assigned (so no pre `!moved()` here).
boost::contract::check c = boost::contract::public_function(this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(!other.moved());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(!moved());
BOOST_CONTRACT_ASSERT(other.moved());
})
;
return move(std::forward<circular_buffer>(other));
}
char read() {
boost::contract::check c = boost::contract::public_function(this)
.precondition([&] {
@@ -114,11 +128,6 @@ public:
return data_.at(i);
}
bool moved() const {
boost::contract::check c = boost::contract::public_function(this);
return moved_;
}
private:
circular_buffer& copy(circular_buffer const& other) {
data_ = other.data_;
@@ -137,10 +146,6 @@ private:
std::vector<char> data_;
unsigned index_;
bool moved_;
/* ... */
//]
public:
unsigned index() const {

View File

@@ -20,8 +20,7 @@ template<typename T>
void generic_unary_pack<T>::_1(T const& value, boost::contract::virtual_* v) {
boost::contract::check c = boost::contract::public_function(v, this)
.precondition([&] {
// Derived concrete classes will enforce preconditions.
BOOST_CONTRACT_ASSERT(false);
BOOST_CONTRACT_ASSERT(false); // Defer preconditions to overrides.
})
;
assert(false);
@@ -54,7 +53,7 @@ public:
#undef BASES
// BOOST_CONTRACT_OVERRIDE(_1) would generate reserved symbol `override__1`.
BOOST_CONTRACT_NAMED_OVERRIDE(override1, _1)
BOOST_CONTRACT_NAMED_OVERRIDE(override1, _1) // Generate `override1`.
virtual void _1(T const& value, boost::contract::virtual_* v = 0)
/* override */ {

View File

@@ -7,7 +7,7 @@
#include <limits>
#include <cassert>
//[function
//[non_member
#include <boost/contract.hpp>
// Contract for a non-member function.

View File

@@ -6,11 +6,10 @@
#include <boost/contract.hpp>
#include <string>
#include <cstddef>
#include <cassert>
//[old
char replace(std::string& s, std::size_t index, char x) {
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::check c = boost::contract::function()
@@ -18,7 +17,7 @@ char replace(std::string& s, std::size_t index, char x) {
BOOST_CONTRACT_ASSERT(index < s.size());
})
.old([&] { // ...after preconditions (and invariants) checked.
old_y = BOOST_CONTRACT_OLD(s[index]);
old_y = BOOST_CONTRACT_OLD(s[index]); // Checked `index` in range.
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(s[index] == x);

View File

@@ -36,15 +36,28 @@ private:
};
// Specialize `boost::is_copy_constructible<n>` trait (not needed on C++11):
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
//[old_if_copyable_specialization
#include <boost/type_traits/is_copy_constructible.hpp>
namespace boost {
template<>
struct is_copy_constructible<n> : false_type {};
}
//]
#endif
int main() {
n j, k;
n j, k; // Non copyable (no compiler error but no old-value checks).
j.value = 1;
k.value = 2;
accumulate(j, k);
assert(j.value == 3);
int i = 1;
int i = 1; // Copyable (check old values).
accumulate(i, 2);
assert(i == 3);

View File

@@ -8,7 +8,7 @@
#include <cassert>
#include <vector>
//[old_no_macros
//[old_no_macro
template<typename T>
class vector {
public:

View File

@@ -6,37 +6,36 @@
#include <boost/contract.hpp>
#include <boost/optional.hpp>
#include <vector>
#include <cassert>
//[optional_result
struct surface {
int area;
int perimeter;
// No default constructor.
surface(int area, int perimeter) : area(area), perimeter(perimeter) {}
};
surface squared_surface(int edge) {
boost::optional<surface> result; // No default constructor so use optional.
template<unsigned Index, typename T>
T& get(std::vector<T>& vect) {
boost::optional<T&> result; // Result not initialized here...
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(edge > 0);
BOOST_CONTRACT_ASSERT(Index < vect.size());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(result->area == edge * edge);
BOOST_CONTRACT_ASSERT(result->perimeter == edge * 4);
BOOST_CONTRACT_ASSERT(*result == vect[Index]);
})
;
return *(result = surface(edge * edge, edge * 4));
// Function body (executed after preconditions checked).
return *(result = vect[Index]); // ...result initialized here instead.
}
//]
int main() {
surface s = squared_surface(10);
assert(s.area == 100);
assert(s.perimeter == 40);
std::vector<int> v;
v.push_back(123);
v.push_back(456);
v.push_back(789);
int& x = get<1>(v);
assert(x == 456);
x = -456;
assert(v[1] == -456);
return 0;
}

View File

@@ -0,0 +1,88 @@
// Copyright (C) 2008-2016 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 <boost/optional.hpp>
#include <vector>
#include <cassert>
template<typename T>
class accessible {
public:
virtual T& at(unsigned index, boost::contract::virtual_* v = 0) = 0;
// Could program class invariants and contracts for following too.
virtual T const& operator[](unsigned index) const = 0;
virtual unsigned size() const = 0;
};
//[optional_result_virtual
template<typename T>
T& accessible<T>::at(unsigned index, boost::contract::virtual_* v) {
boost::optional<T&> result;
// Pass `result` right after `v`...
boost::contract::check c = boost::contract::public_function(v, result, this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(index < size());
})
// ...plus postconditions take `result` as a parameter (not capture).
.postcondition([&] (boost::optional<T const&> const& result) {
BOOST_CONTRACT_ASSERT(*result == operator[](index));
})
;
assert(false);
return *result;
}
//]
template<typename T>
class vector
#define BASES public accessible<T>
: BASES
{
public:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
T& at(unsigned index, boost::contract::virtual_* v = 0) /* override */ {
boost::optional<T&> result;
// Pass `result` right after `v`...
boost::contract::check c = boost::contract::public_function<
override_at>(v, result, &vector::at, this, index)
// ...plus postconditions take `result` as parameter (not capture).
.postcondition([&] (boost::optional<T const&> const& result) {
if(index == 0) BOOST_CONTRACT_ASSERT(*result == front());
})
;
return *(result = vect_[index]);
}
// Could program class invariants and contracts for following too.
T const& operator[](unsigned index) const { return vect_[index]; }
unsigned size() const { return vect_.size(); }
T const& front() const { return vect_.front(); }
void push_back(T const& value) { vect_.push_back(value); }
BOOST_CONTRACT_OVERRIDE(at)
private:
std::vector<T> vect_;
};
int main() {
vector<int> v;
v.push_back(123);
v.push_back(456);
v.push_back(789);
int& x = v.at(1);
assert(x == 456);
x = -456;
assert(v.at(1) == -456);
return 0;
}

View File

@@ -83,15 +83,18 @@ public:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
BOOST_CONTRACT_OVERRIDES(str) // Used only once for all `str` overloads.
BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads.
std::string str(boost::contract::virtual_* v = 0) const /* override */ {
std::string result;
boost::contract::check c = boost::contract::public_function<
override_str
// Note the use of `static_cast` (and same in other overloads below).
>(v, result, static_cast<std::string (string_lines::*)(
boost::contract::virtual_*) const>(&string_lines::str), this);
override_str>(
v, result,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<std::string (string_lines::*)(
boost::contract::virtual_*) const>(&string_lines::str),
this
);
return result = str_;
}
@@ -99,23 +102,31 @@ public:
// Overload on (absence of) `const` qualifier.
std::string& str(boost::contract::virtual_* v = 0) /* override */ {
boost::contract::check c = boost::contract::public_function<
override_str
>(v, str_, static_cast<std::string& (string_lines::*)(
boost::contract::virtual_*)>(&string_lines::str), this);
override_str>(
v, str_,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<std::string& (string_lines::*)(
boost::contract::virtual_*)>(&string_lines::str),
this
);
return str_;
}
BOOST_CONTRACT_OVERRIDES(put) // Used only once for all `put` overloads.
BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads.
void put(std::string const& x,
boost::contract::virtual_* v = 0) /* override */ {
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLD(v, str());
boost::contract::check c = boost::contract::public_function<
override_put
>(v, static_cast<void (string_lines::*)(std::string const&,
boost::contract::virtual_*)>(&string_lines::put), this, x)
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(std::string const&,
boost::contract::virtual_*)>(&string_lines::put),
this, x
)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
})
@@ -129,9 +140,13 @@ public:
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLD(v, str());
boost::contract::check c = boost::contract::public_function<
override_put
>(v, static_cast<void (string_lines::*)(char, boost::contract::
virtual_*)>(&string_lines::put), this, x)
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(char,
boost::contract::virtual_*)>(&string_lines::put),
this, x
)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
})
@@ -146,9 +161,13 @@ public:
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLD(v, str());
boost::contract::check c = boost::contract::public_function<
override_put
>(v, static_cast<void (string_lines::*)(int, bool, boost::contract::
virtual_*)>(&string_lines::put), this, x, tab)
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(int, bool,
boost::contract::virtual_*)>(&string_lines::put),
this, x, tab
)
.postcondition([&] {
std::ostringstream s;
s << x;

View File

@@ -10,26 +10,7 @@
//[private_protected
class counter {
// Private and protected functions use `function()` like non-members.
private:
int n_;
void dec() {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(get());
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(
get() + 1 >= std::numeric_limits<int>::min());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == *old_get - 1);
})
;
set(get() - 1);
}
// Private and protected functions use `function()` (like non-members).
protected:
virtual void set(int n, boost::contract::virtual_* = 0) {
boost::contract::check c = boost::contract::function()
@@ -44,6 +25,24 @@ protected:
n_ = n;
}
private:
void dec() {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(get());
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(
get() + 1 >= std::numeric_limits<int>::min());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == *old_get - 1);
})
;
set(get() - 1);
}
int n_;
/* ... */
//]

View File

@@ -10,12 +10,23 @@
//[private_protected_virtual_counter
class counter {
// Private and protected virtual functions declare extra `virtual_* = 0`
// parameter (otherwise they cannot be overridden).
// Virtual private and protected functions still declare extra
// `virtual_* = 0` parameter (otherwise they cannot be overridden).
protected:
virtual void set(int n, boost::contract::virtual_* = 0) {
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(n <= 0);
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == n);
})
;
n_ = n;
}
private:
int n_;
virtual void dec(boost::contract::virtual_* = 0) {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(get());
boost::contract::check c = boost::contract::function()
@@ -30,20 +41,8 @@ private:
set(get() - 1);
}
protected:
virtual void set(int n, boost::contract::virtual_* = 0) {
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(n <= 0);
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == n);
})
;
n_ = n;
}
int n_;
/* ... */
//]
@@ -80,9 +79,22 @@ public:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
// Not overriding from public members so no `override_...`.
// 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);
})
;
virtual void dec(boost::contract::virtual_* v = 0) {
counter::set(n);
}
virtual void dec(boost::contract::virtual_* v = 0) /* override */ {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(v, get());
boost::contract::check c = boost::contract::public_function(v, this)
.precondition([&] {
@@ -97,19 +109,6 @@ public:
set(get() - 10);
}
virtual void set(int n, boost::contract::virtual_* v = 0) {
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);
}
/* ... */
//]

View File

@@ -22,29 +22,9 @@ int main() { return 0; } // Trivial program for MSVC.
#include <limits>
#include <cassert>
//[private_protected_virtual_multi_counter
class counter {
// Private and protected virtual functions declare extra `virtual_* = 0`
// parameter (otherwise they cannot be overridden).
private:
int n_;
virtual void dec(boost::contract::virtual_* = 0) {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(get());
boost::contract::check c = boost::contract::function()
.precondition([&] {
BOOST_CONTRACT_ASSERT(
get() + 1 >= std::numeric_limits<int>::min());
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == *old_get - 1);
})
;
set(get() - 1);
}
// Virtual private and protected functions still declare extra
// `virtual_* = 0` parameter (otherwise they cannot be overridden).
protected:
virtual void set(int n, boost::contract::virtual_* = 0) {
boost::contract::check c = boost::contract::function()
@@ -59,8 +39,23 @@ protected:
n_ = n;
}
/* ... */
//]
private:
virtual void dec(boost::contract::virtual_* = 0) {
boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLD(get());
boost::contract::check c = boost::contract::function()
.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 {
@@ -135,7 +130,7 @@ int countable::get(boost::contract::virtual_* v) const {
//[private_protected_virtual_multi_counter10
class counter10
#define BASES public countable, public counter
#define BASES public countable, public counter // Multiple inheritance.
: BASES
{
public:
@@ -144,7 +139,21 @@ public:
// Overriding from public members from `countable` so use `override_...`.
virtual void dec(boost::contract::virtual_* v = 0) {
virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ {
boost::contract::check c = boost::contract::public_function<
override_set>(v, &counter10::set, this, n)
.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_OLD(v, get());
boost::contract::check c = boost::contract::public_function<
override_dec>(v, &counter10::dec, this)
@@ -160,21 +169,7 @@ public:
set(get() - 10);
}
virtual void set(int n, boost::contract::virtual_* v = 0) {
boost::contract::check c = boost::contract::public_function<
override_set>(v, &counter10::set, this, n)
.precondition([&] {
BOOST_CONTRACT_ASSERT(n % 10 == 0);
})
.postcondition([&] {
BOOST_CONTRACT_ASSERT(get() == n);
})
;
counter::set(n);
}
BOOST_CONTRACT_OVERRIDES(dec, set)
BOOST_CONTRACT_OVERRIDES(set, dec)
/* ... */
//]

View File

@@ -5,103 +5,89 @@
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
#include <boost/contract.hpp>
#include <boost/optional.hpp>
#include <vector>
#include <cassert>
//[pure_virtual_public_base
struct surface {
int area;
int perimeter;
// No default constructor.
surface(int area, int perimeter) : area(area), perimeter(perimeter) {}
};
class shape {
template<typename Iterator>
class range {
public:
virtual surface get_surface(boost::contract::virtual_* v = 0) const = 0;
};
// Pure virtual function declaration (contract not here, below instead).
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 function definition (and contract) out-of-line (usual in C++).
surface shape::get_surface(boost::contract::virtual_* v) const {
boost::optional<surface> result;
// 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`...
boost::contract::check c = boost::contract::public_function(v, result, this)
// ...and postconditions take `result` as parameter (not capture).
.postcondition([&] (boost::optional<surface const&> const& result) {
BOOST_CONTRACT_ASSERT(result->area > 0);
BOOST_CONTRACT_ASSERT(result->perimeter > 0);
// ...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).
return *result;
assert(false); // Pure function body never executed by this library.
return result;
}
//]
//[pure_virtual_public_derived
class square
#define BASES private boost::contract::constructor_precondition<square>, \
public shape
template<typename T>
class vector
#define BASES public range<typename std::vector<T>::iterator>
: BASES
{
public:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
typedef typename std::vector<T>::iterator iterator;
surface get_surface(boost::contract::virtual_* v = 0) const /* override */ {
boost::optional<surface> result;
iterator begin(boost::contract::virtual_* v = 0) /* override */ {
iterator result;
// Again, pass result right after `v`...
boost::contract::check c = boost::contract::public_function<
override_get_surface>(v, result, &square::get_surface, this)
.postcondition([&] (boost::optional<surface const&> const& result) {
BOOST_CONTRACT_ASSERT(result->area == edge() * edge());
BOOST_CONTRACT_ASSERT(result->perimeter == edge() * 4);
override_begin>(v, result, &vector::begin, this)
// ...plus postconditions take `result` as parameter (not capture).
.postcondition([&] (iterator const& result) {
if(!empty()) BOOST_CONTRACT_ASSERT(*result == front());
})
;
return *(result = surface(edge() * edge(), edge() * 4));
return result = vect_.begin();
}
BOOST_CONTRACT_OVERRIDE(get_surface)
/* ... */
//]
explicit square(int edge) :
boost::contract::constructor_precondition<square>([&] {
BOOST_CONTRACT_ASSERT(edge > 0);
}),
edge_(edge)
{
// Check invariants.
boost::contract::check c = boost::contract::constructor(this);
}
~square() {
// Check invariants.
boost::contract::check c = boost::contract::destructor(this);
}
// Could program class invariants and contracts for the following too.
iterator end() { return vect_.end(); }
bool empty() const { return vect_.empty(); }
T const& front() const { return vect_.front(); }
void push_back(T const& value) { vect_.push_back(value); }
int edge() const {
// Check invariants.
boost::contract::check c = boost::contract::public_function(this);
return edge_;
}
void invarinat() const {
BOOST_CONTRACT_ASSERT(edge() > 0);
}
BOOST_CONTRACT_OVERRIDE(begin)
private:
int edge_;
std::vector<T> vect_;
};
int main() {
square sq(10);
surface s = sq.get_surface();
assert(s.area == 100);
assert(s.perimeter == 40);
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
range<std::vector<int>::iterator>& r = v;
assert(*(r.begin()) == 1);
return 0;
}

View File

@@ -12,7 +12,7 @@
//[throw_on_failure_cstring
struct too_large_error {};
template<std::size_t MaxSize>
template<unsigned MaxSize>
class cstring
#define BASES private boost::contract::constructor_precondition<cstring< \
MaxSize> >
@@ -39,7 +39,7 @@ public:
;
size_ = std::strlen(chars);
for(std::size_t i = 0; i < size_; ++i) chars_[i] = chars[i];
for(unsigned i = 0; i < size_; ++i) chars_[i] = chars[i];
chars_[size_] = '\0';
}
@@ -47,8 +47,8 @@ public:
// Check invariants.
boost::contract::check c = boost::contract::destructor(this);
}
std::size_t size() const {
unsigned size() const {
// Check invariants.
boost::contract::check c = boost::contract::public_function(this);
return size_;
@@ -62,23 +62,32 @@ public:
private:
char chars_[MaxSize + 1];
std::size_t size_;
unsigned size_;
};
//[throw_on_failure_handler
int main() {
boost::contract::set_specification_failure(
[] (boost::contract::from context) {
if(context == boost::contract::from_destructor) {
// Ignore exception because destructors should never throw.
std::clog << "destructor contract failed (ignored)" <<
std::endl;
} else throw; // Rethrow (assertion_failure, too_large_error, etc.).
boost::contract::set_precondition_failure(
boost::contract::set_postcondition_failure(
boost::contract::set_invariant_failure(
boost::contract::set_old_failure(
[] (boost::contract::from where) {
if(where == boost::contract::from_destructor) {
// Cannot throw from destructors in C++.
std::clog << "ignored destructor contract failure" << std::endl;
} else throw; // Re-throw (assertion_failure, user-defined, etc.).
}
))));
boost::contract::set_except_failure(
[] (boost::contract::from where) {
// Already an active exception so can't throw another in C++.
std::clog << "ignored exception guarantee failure" << std::endl;
}
);
boost::contract::set_check_failure( // Then do not use CHECK in destructors.
boost::contract::set_check_failure(
[] {
throw; // Rethrow (assertion_failure, too_large_error, etc.).
// But now CHECK cannot be used within destructor implementations.
throw; // Re-throw (assertion_failure, user-defined, etc.).
}
);

View File

@@ -14,16 +14,17 @@
//[union
union positive {
static void static_invariant() {
public:
static void static_invariant() { // Static class invariants.
BOOST_CONTRACT_ASSERT(instances() >= 0);
}
void invariant() const {
void invariant() const { // Class invariants.
BOOST_CONTRACT_ASSERT(i_ > 0);
BOOST_CONTRACT_ASSERT(d_ > 0);
}
explicit positive(int x) {
explicit positive(int x) { // Contracts for a constructor.
// Unions cannot have bases so ctor preconditions here.
boost::contract::constructor_precondition<positive> pre([&] {
BOOST_CONTRACT_ASSERT(x > 0);
@@ -40,6 +41,41 @@ union positive {
++instances_;
}
~positive() { // Contracts for the destructor.
boost::contract::old_ptr<int> old_instances =
BOOST_CONTRACT_OLD(instances());
boost::contract::check c = boost::contract::destructor(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1);
})
;
--instances_;
}
void get(int& x) { // Contracts for a public function.
boost::contract::check c = boost::contract::public_function(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(x > 0);
});
;
x = i_;
}
static int instances() { // Contracts for a static public function.
boost::contract::check c = boost::contract::public_function<positive>();
return instances_;
}
private:
int i_;
double d_;
/* ... */
//]
public:
explicit positive(double x) {
// Unions cannot have bases so ctor preconditions here.
boost::contract::constructor_precondition<positive> pre([&] {
@@ -56,28 +92,6 @@ union positive {
d_ = x;
++instances_;
}
~positive() {
boost::contract::old_ptr<int> old_instances =
BOOST_CONTRACT_OLD(instances());
boost::contract::check c = boost::contract::destructor(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1);
})
;
--instances_;
}
void get(int& x) {
boost::contract::check c = boost::contract::public_function(this)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(x > 0);
});
;
x = i_;
}
void get(double& x) {
boost::contract::check c = boost::contract::public_function(this)
@@ -89,17 +103,6 @@ union positive {
x = d_;
}
static int instances() {
boost::contract::check c = boost::contract::public_function<positive>();
return instances_;
}
private:
int i_;
double d_;
/* ... */
//]
#ifndef BOOST_GCC // G++ does not support static union members yet.
static int instances_;
#endif

View File

@@ -21,19 +21,19 @@ public:
boost::contract::check c = boost::contract::destructor(this);
}
void m() { // Check const invariant (at entry and exit if no throw).
void m() { // Check const invariant (at entry and exit).
boost::contract::check c = boost::contract::public_function(this);
}
void c() const { // Check const invariant (at entry and exit if no throw).
void c() const { // Check const invariant (at entry and exit).
boost::contract::check c = boost::contract::public_function(this);
}
void v() volatile { // Check cv invariant (at entry and exit if no throw).
void v() volatile { // Check cv invariant (at entry and exit).
boost::contract::check c = boost::contract::public_function(this);
}
void cv() const volatile { // Check cv inv. (at entry and exit if no throw).
void cv() const volatile { // Check cv invariant (at entry and exit).
boost::contract::check c = boost::contract::public_function(this);
}
};