mirror of
https://github.com/boostorg/contract.git
synced 2026-02-26 04:32:22 +00:00
finished all docs up to reference section
This commit is contained in:
@@ -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 ]
|
||||
;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -112,7 +112,7 @@ private:
|
||||
std::vector<char> vect_;
|
||||
};
|
||||
|
||||
//[base_types_no_macros
|
||||
//[base_types_no_macro
|
||||
#include <boost/mpl/vector.hpp>
|
||||
|
||||
class chars :
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
//]
|
||||
|
||||
|
||||
62
example/features/friend.cpp
Normal file
62
example/features/friend.cpp
Normal 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;
|
||||
}
|
||||
|
||||
54
example/features/friend_invariant.cpp
Normal file
54
example/features/friend_invariant.cpp
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
@@ -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
35
example/features/loop.cpp
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */ {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <limits>
|
||||
#include <cassert>
|
||||
|
||||
//[function
|
||||
//[non_member
|
||||
#include <boost/contract.hpp>
|
||||
|
||||
// Contract for a non-member function.
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
//[old_no_macros
|
||||
//[old_no_macro
|
||||
template<typename T>
|
||||
class vector {
|
||||
public:
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
88
example/features/optional_result_virtual.cpp
Normal file
88
example/features/optional_result_virtual.cpp
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
/* ... */
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.).
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user