diff --git a/doc/advanced_topics.qbk b/doc/advanced_topics.qbk index 3997a67..71c6d27 100644 --- a/doc/advanced_topics.qbk +++ b/doc/advanced_topics.qbk @@ -159,6 +159,41 @@ The [macroref BOOST_CONTRACT_NAMED_OVERRIDE] macro can be used for function name [endsect] +[section Move Operations] + +As with all public operations of a class, also move operations should maintain class invariants (see also __Stroustrup13__, p. 520). +Specifically, C++ requires the following: + +* The moved-from object can be copy assigned. +* The moved-from object can be move assigned. +* The moved-from object can be destroyed. +[footnote +If not anything else, this requires that class invariants are maintained by move operations because the destructor of the moved-from object requires that class invariants are true at its entry (as always with destructors, see also __Destructor_Calls__). +] + +Thus both the move constructor and the move assignment operator need to maintain the class invariants of the moved-from object and their contracts can be programmed using [funcref boost::contract::constructor] and [funcref boost::contract::public_function] as always for constructors and public member functions, for example (see also [@../../example/features/move.cpp =move.cpp=]): + +[import ../example/features/move.cpp] +[move] + +This example requires that it is possible to call the public member function `move()` on the moved-from object. +This allows to make explicit the precondition that except for destructor, copy and move assignments all other public member functions cannot be called on a moved-from object. +This assumption is usually implicit in C++ (i.e., documented by the standard but not checked by the language at run-time). +If it is is not possible (e.g., due to some optimized implementation of the move operations) to have such a public `move()` member function, the private `moved_` member (or similar) can be used to program class invariants and preconditions (and that will just relay on the usual implicit C++ assumption on moved-from object because users will not be able to fully check preconditions and class invariants before calling functions of a moved-from object). + +[endsect] + +[section Unions] + +In C++, a `union` cannot have virtual member functions, bases classes, and cannot be used as a base class thus subcontracting ([classref boost::contract::virtual_], [macroref BOOST_CONTRACT_OVERRIDE], etc.) do not apply to unions. +Also a `union` cannot inherit from [classref boost::contract::constructor_precondition] (because it cannot have base classes) so such a class is used to declare a local object that checks constructor preconditions (see `pre` in the example below). +A part from that, this library is used as usual to program contracts for unions, for example (see also [@../../example/features/union.cpp =union.cpp=]): + +[import ../example/features/union.cpp] +[union] + +[endsect] + [section Volatile Class Invariants] This library allows to specify a different set of class invariants to be checked for public volatile member functions. diff --git a/doc/bibliography.qbk b/doc/bibliography.qbk index e559926..5961a7d 100644 --- a/doc/bibliography.qbk +++ b/doc/bibliography.qbk @@ -69,7 +69,7 @@ This section lists all references consulted while designing and developing this [#Stroustrup94_anchor] [Stroustrup94] B. Stroustrup. /The Design and Evolution of C++/. Addison Wesley, 1994. -[#Stroustrup97_anchor] [Stroustrup97] B. Stroustrup. /The C++ Programming Language/. Prentice-Hall, 2nd Edition, 1997. +[#Stroustrup13_anchor] [Stroustrup13] B. Stroustrup. /The C++ Programming Language/. Addison Wesley, 4th Edition, 2013. [#Tandin04_anchor] [Tandin04] A. Tandin. [@http://www.codeproject.com/KB/macros/DbC_and_Doxygen.aspx /Design by Contract macros for C++ and link to Doxygen/]. 2004. diff --git a/doc/contract.qbk b/doc/contract.qbk index ace1c9d..988ff0c 100644 --- a/doc/contract.qbk +++ b/doc/contract.qbk @@ -86,8 +86,8 @@ [def __N2914__ [link N2914_anchor \[N2914\]]] [def __SPARKAda__ [link SPARKAda_anchor \[SPARKAda\]]] [def __SpecSharp__ [link SpecSharp_anchor \[SpecSharp\]]] -[def __Stroustrup97__ [link Stroustrup97_anchor \[Stroustrup97\]]] [def __Stroustrup94__ [link Stroustrup94_anchor \[Stroustrup94\]]] +[def __Stroustrup13__ [link Stroustrup13_anchor \[Stroustrup13\]]] [def __Tandin04__ [link Tandin04_anchor \[Tandin04\]]] [:['["Our field needs more formality, but the profession has not realized it yet.]]] diff --git a/doc/examples.qbk b/doc/examples.qbk index 43750d5..c667f47 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -1,10 +1,10 @@ [section Examples] -This section lists a few non-trivial examples taken from different Contract Programming sources and re-implemented using this library. +This section lists examples taken from different Contract Programming sources and re-implemented using this library. -Some of these examples might be from old sources, containing old or obsolete code practices, not optimized for execution speed, and they be more relevant in the context of other programming languages different from C++ (because the considered sources were also for the Eiffel and D programming languages). -Nevertheless, programmers are encouraged to review these examples to see a few diverse uses of this library that could program contracts in ways similar to what programmers need in their specific C++ applications. +Some of these examples might be from old sources, containing old or obsolete code practices, not optimized for execution speed, and they be more relevant in the context programming languages other than C++. +Nevertheless, programmers are encouraged to review these examples to see a few diverse usages of this library that might be relevant for the contracts they need to write in their code. Sources: @@ -12,21 +12,20 @@ Sources: * __Meyer97__: Examples using the Eiffel programming language and reprogrammed using this library for C++. * __Mitchell02__: Additional examples using the Eiffel programming language and reprogrammed using this library for C++. * __Cline90__: Examples from a very early proposal called Annotated C++ (A++) to add Contract Programming to C++ (A++ was never implemented or proposed for addition to the standard). -* __Stroustrup97__: One example that shows the importance of class invariants and how to configure this library to throw exceptions instead of terminating the program on contract failure. -Most interesting examples: +A few notable examples: -* [link contract__.examples.__n1962___vector__comparison_with_c___proposed_syntax \[N1962\] Vector]: The complete contracts of `std::vector` and a comparison with __N1962__ syntax. -* [link contract__.examples.__n1962___square_root__default_parameters_and_comparison_with_d_syntax \[N1962\] Square Root]: A comparison with D syntax. +* [link contract__.examples.__n1962___vector__comparison_with_c___proposed_syntax \[N1962\] Vector]: Complete contracts for `std::vector` and a comparison with __N1962__ syntax. +* [link contract__.examples.__n1962___square_root__default_parameters_and_comparison_with_d_syntax \[N1962\] Square Root]: Comparison with D syntax. * [link contract__.examples.__mitchell02___counter__subcontracting_and_virtual_specifiers__final__override__new__and_pure_virtual_ \[Mitchell02\] Counter]: Subcontracting. -* [link contract__.examples.__meyer97___stack4__comparison_with_eiffel_syntax \[Meyer97\] Stack4]: A comparison with Eiffel syntax. -* [link contract__.examples.__cline90___vector__comparison_with_a___proposed_syntax \[Cline90\] Vector]: A comparison with A++ syntax. +* [link contract__.examples.__meyer97___stack4__comparison_with_eiffel_syntax \[Meyer97\] Stack4]: Comparison with Eiffel syntax. +* [link contract__.examples.__cline90___vector__comparison_with_a___proposed_syntax \[Cline90\] Vector]: Comparison with A++ syntax. [heading \[N1962\] Vector: Comparison with C++ proposal's syntax] [import ../example/n1962/vector.cpp] [import ../example/n1962/vector_n1962.hpp] [table - [ [This Library] [\[N1962\] Proposal (not part of C++)] ] + [ [This Library] [Contract \[N1962\] and Static-If \[N3613\] Proposals (neither part of C++)] ] [ [[n1962_vector]] [[n1962_vector_n1962]] ] ] @@ -60,7 +59,7 @@ Most interesting examples: [import ../example/meyer97/stack4.e] [table [ [This Library] [The Eiffel Programming Language] ] - [ [[meyer97_stack4_header]] [[meyer97_stack4_e]] ] + [ [[meyer97_stack4]] [[meyer97_stack4_e]] ] [ [[meyer97_stack4_main]] [] ] ] @@ -110,10 +109,6 @@ Most interesting examples: [import ../example/mitchell02/counter_main.cpp] [mitchell02_counter_main] -[heading \[Stroustrup97\] String: Throw when contracts fail] -[import ../example/stroustrup97/string.cpp] -[stroustrup97_string] - [heading \[Cline90\] Vector: Comparison with A++ proposed syntax] [import ../example/cline90/vector.hpp] [import ../example/cline90/vector_main.cpp] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 25c6ae6..f6c6612 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -16,8 +16,10 @@ test-suite features : [ subdir-run features : pure_virtual_public ] [ subdir-run features : overload ] [ subdir-run features : named_override ] + [ subdir-run features : move ] + [ subdir-run features : union ] [ subdir-run features : volatile ] - [ subdir-run features : noncopyable_old ] + [ subdir-run features : old_noncopyable ] [ subdir-run features : check_if ] [ subdir-run features : access ] [ subdir-run features : separate_body ] @@ -29,6 +31,15 @@ test-suite features : [ subdir-run features : no_lambdas_local_func ] ; +test-suite n1962 : + [ subdir-run n1962 : vector ] + [ subdir-run n1962 : sqrt ] + [ subdir-run n1962 : circle ] + [ subdir-run n1962 : equal ] + [ subdir-run n1962 : factorial ] + [ subdir-run n1962 : sum ] +; + test-suite meyer97 : [ subdir-run meyer97 : stack4_main ] [ subdir-run meyer97 : stack3 ] @@ -52,16 +63,3 @@ test-suite cline90 : [ subdir-run cline90 : calendar ] ; -test-suite n1962 : - [ subdir-run n1962 : vector ] - [ subdir-run n1962 : sqrt ] - [ subdir-run n1962 : circle ] - [ subdir-run n1962 : equal ] - [ subdir-run n1962 : factorial ] - [ subdir-run n1962 : sum ] -; - -test-suite stroustrup97 : - [ subdir-run stroustrup97 : string ] -; - diff --git a/example/cline90/calendar.cpp b/example/cline90/calendar.cpp index 9380b6c..e5a20e2 100644 --- a/example/cline90/calendar.cpp +++ b/example/cline90/calendar.cpp @@ -1,10 +1,11 @@ //[cline90_calendar #include -#include +#include class calendar { -public: + friend class boost::contract::access; + void invariant() const { BOOST_CONTRACT_ASSERT(month() >= 1); BOOST_CONTRACT_ASSERT(month() <= 12); @@ -12,8 +13,9 @@ public: BOOST_CONTRACT_ASSERT(date() <= days_in(month())); } +public: calendar() : month_(1), date_(31) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(month() == 1); BOOST_CONTRACT_ASSERT(date() == 31); @@ -22,21 +24,24 @@ public: } virtual ~calendar() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } int month() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return month_; } int date() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return date_; } void reset(int new_month) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(new_month >= 1); BOOST_CONTRACT_ASSERT(new_month <= 12); @@ -52,7 +57,7 @@ public: private: static int days_in(int month) { int result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .precondition([&] { BOOST_CONTRACT_ASSERT(month >= 1); BOOST_CONTRACT_ASSERT(month <= 12); @@ -71,13 +76,13 @@ private: int main() { calendar cal; - BOOST_TEST_EQ(cal.date(), 31); - BOOST_TEST_EQ(cal.month(), 1); + assert(cal.date() == 31); + assert(cal.month() == 1); cal.reset(8); // Set month - BOOST_TEST_EQ(cal.month(), 8); + assert(cal.month() == 8); - return boost::report_errors(); + return 0; } //] diff --git a/example/cline90/stack.cpp b/example/cline90/stack.cpp index b4ca860..cc4288f 100644 --- a/example/cline90/stack.cpp +++ b/example/cline90/stack.cpp @@ -1,28 +1,28 @@ //[cline90_stack #include -#include +#include +// NOTE: Incomplete contract assertions, addressing only `empty` and `full`. template class stack #define BASES private boost::contract::constructor_precondition > : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - // NOTE: Incomplete contract assertions, addressing only `empty` and `full`. - +public: explicit stack(int capacity) : boost::contract::constructor_precondition([&] { BOOST_CONTRACT_ASSERT(capacity >= 0); }), data_(new T[capacity]), capacity_(capacity), size_(0) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->empty()); + BOOST_CONTRACT_ASSERT(empty()); BOOST_CONTRACT_ASSERT(full() == (capacity == 0)); }) ; @@ -31,22 +31,22 @@ public: } virtual ~stack() { - auto c = boost::contract::destructor(this); + boost::contract::guard c = boost::contract::destructor(this); delete[] data_; } bool empty() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return size_ == 0; } bool full() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return size_ == capacity_; } void push(T const& value) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!full()); }) @@ -59,7 +59,7 @@ public: } T pop() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -80,8 +80,8 @@ private: int main() { stack s(3); s.push(123); - BOOST_TEST_EQ(s.pop(), 123); - return boost::report_errors(); + assert(s.pop() == 123); + return 0; } //] diff --git a/example/cline90/vector.hpp b/example/cline90/vector.hpp index 5d7d3c6..028d28c 100644 --- a/example/cline90/vector.hpp +++ b/example/cline90/vector.hpp @@ -5,21 +5,21 @@ #include +// NOTE: Incomplete contract assertions, addressing only `size`. template class vector #define BASES private boost::contract::constructor_precondition > : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - // NOTE: Incomplete contract assertions, addressing only `size`. - void invariant() const { BOOST_CONTRACT_ASSERT(size() >= 0); } +public: explicit vector(int count = 10) : boost::contract::constructor_precondition([&] { BOOST_CONTRACT_ASSERT(count >= 0); @@ -27,9 +27,9 @@ public: data_(new T[count]), size_(count) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->size() == count); + BOOST_CONTRACT_ASSERT(size() == count); }) ; @@ -37,22 +37,22 @@ public: } virtual ~vector() { - auto c = boost::contract::destructor(this); + boost::contract::guard c = boost::contract::destructor(this); delete[] data_; } int size() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return size_; // Non-negative result already checked by invariant. } void resize(int count) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count >= 0); }) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->size() == count); + BOOST_CONTRACT_ASSERT(size() == count); }) ; @@ -64,7 +64,7 @@ public: } T& operator[](int index) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(index >= 0); BOOST_CONTRACT_ASSERT(index < size()); @@ -75,7 +75,7 @@ public: } T const& operator[](int index) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(index >= 0); BOOST_CONTRACT_ASSERT(index < size()); diff --git a/example/cline90/vector_axx.hpp b/example/cline90/vector_axx.hpp index ef218b9..d893d04 100644 --- a/example/cline90/vector_axx.hpp +++ b/example/cline90/vector_axx.hpp @@ -1,34 +1,52 @@ //[cline90_vector_axx -// Extra newlines, etc used to align text with this library code. +// Extra spaces, newlines, etc. for visual alignment with this library code. -template< typename T> -class vector -{ - legal: size() >= 0; // Class invariants (legal). +template +class vector { - public: explicit vector ( int count = 10 ) - : data_(new T[count]), size_(count) + + + + + + +legal: // Class invariants (legal). + size() >= 0; + + +public: + explicit vector(int count = 10) : + data_(new T[count]), + size_(count) { for(int i = 0; i < size_; ++i) data_[i] = T(); } - public: virtual ~vector ( void ) - { - delete[] data_; - } - - public: int size ( void ) const - { - return size_; - } - public: void resize ( int count ) - { + + + + + + + + + virtual ~vector() { delete[] data_; } + + + + + int size() const { return size_; } + + + + + void resize(int count) { T* slice = new T[count]; for(int i = 0; i < count && i < size_; ++i) slice[i] = data_[i]; delete[] data_; @@ -36,31 +54,42 @@ class vector size_ = count; } - public: T& operator[] ( int index ) - { - return data_[index]; - } + + + T& operator[](int index) { return data_[index]; } + + + + + + + + + + + + + + + + + + T& operator[](int index) const { return data_[index]; } - // Preconditions (require) and postconditions (promise) for each function. - axioms: [ int count; require count >= 0; promise size() == count ] - vector(count); - axioms: [ int count; require count >= 0; promise size() == count ] - resize(count); - axioms: [ int index; require index >= 0 && index < size() ] - (*this)[x]; - private: T* data_; - private: int size_; + + +axioms: // Preconditions (require) and postconditions (promise) for each func. + [int count; require count >= 0; promise size() == count] vector(count); + [int count; require count >= 0; promise size() == count] resize(count); + [int index; require index >= 0 && index < size()] (*this)[x]; // Op[]. + [int index; require index >= 0 && index < size()] (*this)[x] const; // Op[]. + +private: + T* data_; + int size_; }; - - - - - - - - - +// End. //] diff --git a/example/cline90/vector_main.cpp b/example/cline90/vector_main.cpp index 514761f..0778b0e 100644 --- a/example/cline90/vector_main.cpp +++ b/example/cline90/vector_main.cpp @@ -1,18 +1,18 @@ //[cline90_vector_main #include "vector.hpp" -#include +#include int main() { vector v (3); - BOOST_TEST_EQ(v.size(), 3); + assert(v.size() == 3); v[0] = 123; v.resize(2); - BOOST_TEST_EQ(v[0], 123); - BOOST_TEST_EQ(v.size(), 2); + assert(v[0] == 123); + assert(v.size() == 2); - return boost::report_errors(); + return 0; } //] diff --git a/example/cline90/vstack.cpp b/example/cline90/vstack.cpp index 5589187..ae863a5 100644 --- a/example/cline90/vstack.cpp +++ b/example/cline90/vstack.cpp @@ -3,26 +3,26 @@ #include "vector.hpp" #include #include -#include #include +// NOTE: Incomplete contract assertions, addressing `empty` and `full` only. template class abstract_stack { public: - // NOTE: Incomplete contract assertions, addressing `empty` and `full` only. - abstract_stack() { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) // Postcondition: empty() (but it cannot be checked here to avoid // calling pure virtual function length() during construction). ; } - virtual ~abstract_stack() { auto c = boost::contract::destructor(this); } + virtual ~abstract_stack() { + boost::contract::guard c = boost::contract::destructor(this); + } bool full() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(result == (length() == capacity())); }) @@ -33,7 +33,7 @@ public: bool empty() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(result = (length() == 0)); }) @@ -56,38 +56,42 @@ public: template int abstract_stack::length(boost::contract::virtual_* v) const { int result; - auto c = boost::contract::public_function(v, result, this) + boost::contract::guard c = boost::contract::public_function(v, result, this) .postcondition([&] (int const& result) { BOOST_CONTRACT_ASSERT(result >= 0); }) ; - assert(false); return result; + assert(false); + return result; } template int abstract_stack::capacity(boost::contract::virtual_* v) const { int result; - auto c = boost::contract::public_function(v, result, this) + boost::contract::guard c = boost::contract::public_function(v, result, this) .postcondition([&] (int const& result) { BOOST_CONTRACT_ASSERT(result >= 0); }) ; - assert(false); return result; + assert(false); + return result; } template T const& abstract_stack::item(boost::contract::virtual_* v) const { - auto c = boost::contract::public_function(v, this) + boost::optional result; + boost::contract::guard c = boost::contract::public_function(v, result, this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) ; - assert(false); return *boost::optional(); + assert(false); + return *result; } template void abstract_stack::push(T const& value, boost::contract::virtual_* v) { - auto c = boost::contract::public_function(v, this) + boost::contract::guard c = boost::contract::public_function(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(!full()); }) @@ -101,8 +105,8 @@ void abstract_stack::push(T const& value, boost::contract::virtual_* v) { template T const& abstract_stack::pop(boost::contract::virtual_* v) { boost::optional result; - auto old_item = BOOST_CONTRACT_OLDOF(v, item()); - auto c = boost::contract::public_function(v, result, this) + boost::contract::old_ptr old_item = BOOST_CONTRACT_OLDOF(v, item()); + boost::contract::guard c = boost::contract::public_function(v, result, this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -111,14 +115,15 @@ T const& abstract_stack::pop(boost::contract::virtual_* v) { BOOST_CONTRACT_ASSERT(*result == *old_item); }) ; - assert(false); return *boost::optional(); + assert(false); + return *result; } template void abstract_stack::clear(boost::contract::virtual_* v) { - auto c = boost::contract::public_function(v, this) + boost::contract::guard c = boost::contract::public_function(v, this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->empty()); + BOOST_CONTRACT_ASSERT(empty()); }) ; assert(false); @@ -130,15 +135,17 @@ class vstack vstack >, public abstract_stack : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + BOOST_CONTRACT_OVERRIDES(length, capacity, item, push, pop, clear) void invariant() const { BOOST_CONTRACT_ASSERT(length() >= 0); BOOST_CONTRACT_ASSERT(length() < capacity()); } +public: explicit vstack(int count = 10) : boost::contract::constructor_precondition([&] { BOOST_CONTRACT_ASSERT(count >= 0); @@ -146,7 +153,7 @@ public: vect_(count), // OK, executed after precondition so count >= 0. len_(0) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(length() == 0); BOOST_CONTRACT_ASSERT(capacity() == count); @@ -154,58 +161,54 @@ public: ; } - virtual ~vstack() { auto c = boost::contract::destructor(this); } + virtual ~vstack() { + boost::contract::guard c = boost::contract::destructor(this); + } // Inherited from abstract_stack. virtual int length(boost::contract::virtual_* v = 0) const /* override */ { int result; - auto c = boost::contract::public_function( - v, result, &vstack::length, this); + boost::contract::guard c = boost::contract::public_function< + override_length>(v, result, &vstack::length, this); return result = len_; } - BOOST_CONTRACT_OVERRIDE(length) virtual int capacity(boost::contract::virtual_* v = 0) const /* override */ { int result; - auto c = boost::contract::public_function( - v, result, &vstack::capacity, this); + boost::contract::guard c = boost::contract::public_function< + override_capacity>(v, result, &vstack::capacity, this); return result = vect_.size(); } - BOOST_CONTRACT_OVERRIDE(capacity) virtual T const& item(boost::contract::virtual_* v = 0) const /* override */ { boost::optional result; - auto c = boost::contract::public_function( - v, result, &vstack::item, this); + boost::contract::guard c = boost::contract::public_function< + override_item>(v, result, &vstack::item, this); return *(result = vect_[len_ - 1]); } - BOOST_CONTRACT_OVERRIDE(item) virtual void push(T const& value, boost::contract::virtual_* v = 0) /* override */ { - auto c = boost::contract::public_function( - v, &vstack::push, this, value); + boost::contract::guard c = boost::contract::public_function< + override_push>(v, &vstack::push, this, value); vect_[len_++] = value; } - BOOST_CONTRACT_OVERRIDE(push) virtual T const& pop(boost::contract::virtual_* v = 0) /* override */ { boost::optional result; - auto c = boost::contract::public_function( - v, result, &vstack::pop, this); + boost::contract::guard c = boost::contract::public_function< + override_pop>(v, result, &vstack::pop, this); return *(result = vect_[--len_]); } - BOOST_CONTRACT_OVERRIDE(pop) virtual void clear(boost::contract::virtual_* v = 0) /* override */ { - auto c = boost::contract::public_function( - v, &vstack::clear, this); + boost::contract::guard c = boost::contract::public_function< + override_clear>(v, &vstack::clear, this); len_ = 0; } - BOOST_CONTRACT_OVERRIDE(clear); private: vector vect_; @@ -214,13 +217,13 @@ private: int main() { vstack s(3); - BOOST_TEST_EQ(s.capacity(), 3); + assert(s.capacity() == 3); s.push(123); - BOOST_TEST_EQ(s.length(), 1); - BOOST_TEST_EQ(s.pop(), 123); + assert(s.length() == 1); + assert(s.pop() == 123); - return boost::report_errors(); + return 0; } //] diff --git a/example/features/move.cpp b/example/features/move.cpp new file mode 100644 index 0000000..a31d63d --- /dev/null +++ b/example/features/move.cpp @@ -0,0 +1,191 @@ + +#include +#include +#include +#include + +//[move +class circular_buffer : + private boost::contract::constructor_precondition { +public: + void invariant() const { + if(!moved()) { // Do not check (some) invariants for moved-from objects. + BOOST_CONTRACT_ASSERT(index() < size()); + } + } + + explicit circular_buffer(std::vector const& data, + unsigned start = 0) : + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(start < data.size()); + }), + data_(data), + index_(start), + moved_(false) + { + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + } + + ~circular_buffer() { + // Moved-from can always be destroyed (so no pre `!moved()` here). + boost::contract::guard c = boost::contract::destructor(this); + } + + // Copy constructor. + /* implicit */ circular_buffer(circular_buffer const& other) : + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + { + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + copy(other); + } + + // Copy assignment. + circular_buffer& operator=(circular_buffer const& other) { + // Moved-from can be (copy) assigned (so no pre `!moved()` here). + boost::contract::guard c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + return copy(other); + } + + // Move constructor. + /* implicit */ circular_buffer(circular_buffer&& other) : + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(!other.moved()); + }) + { + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + BOOST_CONTRACT_ASSERT(other.moved()); + }) + ; + + move(std::forward(other)); + } + + // Move assignment. + circular_buffer& operator=(circular_buffer&& other) { + // Moved-from can be (move) assigned (so no pre `!moved()` here). + boost::contract::guard 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(other)); + } + + char read() { + boost::contract::guard c = boost::contract::public_function(this) + .precondition([&] { + BOOST_CONTRACT_ASSERT(!moved()); + }) + ; + + unsigned i = index_++; + if(index_ == data_.size()) index_ = 0; // Circular. + return data_.at(i); + } + + bool moved() const { + boost::contract::guard c = boost::contract::public_function(this); + return moved_; + } + +private: + circular_buffer& copy(circular_buffer const& other) { + data_ = other.data_; + index_ = other.index_; + moved_ = false; + return *this; + } + + circular_buffer& move(circular_buffer&& other) { + data_ = std::move(other.data_); + index_ = std::move(other.index_); + moved_ = false; + other.moved_ = true; // Mark moved-from object. + return *this; + } + + std::vector data_; + unsigned index_; + bool moved_; + + /* ... */ +//] + +public: + unsigned index() const { + boost::contract::guard c = boost::contract::public_function(this); + return index_; + } + + unsigned size() const { + boost::contract::guard c = boost::contract::public_function(this); + return data_.size(); + } +}; + +int main() { + struct err {}; + boost::contract::set_precondition_failure( + [] (boost::contract::from) { throw err(); }); + + { + circular_buffer x({'a', 'b', 'c', 'd'}, 2); + assert(x.read() == 'c'); + + circular_buffer y1 = x; // Copy constructor. + assert(y1.read() == 'd'); + assert(x.read() == 'd'); + + circular_buffer y2({'h'}); + y2 = x; // Copy assignment. + assert(y2.read() == 'a'); + assert(x.read() == 'a'); + + circular_buffer z1 = std::move(x); // Move constructor. + assert(z1.read() == 'b'); + // Calling `x.read()` would fail `!moved()` precondition. + + x = y1; // Moved-from `x` can be copy assigned. + assert(x.read() == 'a'); + assert(y1.read() == 'a'); + + circular_buffer z2({'k'}); + z2 = std::move(x); // Move assignment. + assert(z2.read() == 'b'); + // Calling `x.read()` would fail `!moved()` precondition. + + x = std::move(y2); // Moved-from `x` can be move assigned. + assert(x.read() == 'b'); + // Calling `y2.read()` would fail `!moved()` precondition. + + } // Moved-from `y2` can be destroyed. + + return 0; +} + diff --git a/example/features/noncopyable_old.cpp b/example/features/old_noncopyable.cpp similarity index 93% rename from example/features/noncopyable_old.cpp rename to example/features/old_noncopyable.cpp index f06ffc6..2d073fe 100644 --- a/example/features/noncopyable_old.cpp +++ b/example/features/old_noncopyable.cpp @@ -2,11 +2,11 @@ #include #include -//[noncopyable_old +//[old_noncopyable template void accumulate(T& total, T const& x) { // No compiler error if T has no copy constructor... - boost::contract::noncopyable_old_ptr old_total = + boost::contract::old_ptr_noncopyable old_total = BOOST_CONTRACT_OLDOF(total); boost::contract::guard c = boost::contract::function() .postcondition([&] { diff --git a/example/features/union.cpp b/example/features/union.cpp new file mode 100644 index 0000000..5c04ed6 --- /dev/null +++ b/example/features/union.cpp @@ -0,0 +1,124 @@ + +#include +#include +#include + +#ifdef BOOST_GCC // G++ does not support static union members yet. + int instances_ = 0; +#endif + +//[union +union positive { + static void static_invariant() { + BOOST_CONTRACT_ASSERT(instances() >= 0); + } + + void invariant() const { + BOOST_CONTRACT_ASSERT(i_ > 0); + BOOST_CONTRACT_ASSERT(d_ > 0); + } + + explicit positive(int x) { + // Unions cannot have bases so ctor preconditions here. + boost::contract::constructor_precondition pre([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + boost::contract::old_ptr old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + }) + ; + + i_ = x; + ++instances_; + } + + explicit positive(double x) { + // Unions cannot have bases so ctor preconditions here. + boost::contract::constructor_precondition pre([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + boost::contract::old_ptr old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); + }) + ; + + d_ = x; + ++instances_; + } + + ~positive() { + boost::contract::old_ptr old_instances = + BOOST_CONTRACT_OLDOF(instances()); + boost::contract::guard c = boost::contract::destructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1); + }) + ; + + --instances_; + } + + void get(int& x) { + boost::contract::guard c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + ; + + x = i_; + } + + void get(double& x) { + boost::contract::guard c = boost::contract::public_function(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(x > 0); + }); + ; + + x = d_; + } + + static int instances() { + boost::contract::guard c = boost::contract::public_function(); + return instances_; + } + +private: + int i_; + double d_; + + /* ... */ +//] + #ifndef BOOST_GCC // G++ does not support static union members yet. + static int instances_; + #endif +}; + +#ifndef BOOST_GCC // G++ does not support static union members yet. + int positive::instances_ = 0; +#endif + +int main() { + { + int i = -456; + positive p(123); + assert(p.instances() == 1); + p.get(i); + assert(i == 123); + + double d = -4.56; + positive q(1.23); + assert(q.instances() == 2); + q.get(d); + assert(d == 1.23); + } + assert(positive::instances() == 0); + return 0; +} + diff --git a/example/meyer97/stack3.cpp b/example/meyer97/stack3.cpp index 60646a4..3bf8bde 100644 --- a/example/meyer97/stack3.cpp +++ b/example/meyer97/stack3.cpp @@ -4,12 +4,13 @@ #include "stack4.hpp" #include #include -#include +#include // Dispenser LIFO with max capacity using error codes. template class stack3 { -public: + friend class boost::contract::access; + void invariant() const { if(!error()) { BOOST_CONTRACT_ASSERT(count() >= 0); // Count non-negative. @@ -19,6 +20,7 @@ public: } } +public: enum error_code { no_error = 0, overflow_error, @@ -31,7 +33,7 @@ public: // Create stack for max of n items, if n < 0 set error (no preconditions). explicit stack3(int n, T const& default_value = T()) : stack_(0), error_(no_error) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { // Error if impossible. BOOST_CONTRACT_ASSERT((n < 0) == (error() == size_error)); @@ -50,24 +52,24 @@ public: // Max number of stack items. int capacity() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return stack_.capacity(); } // Number of stack items. int count() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return stack_.count(); } // Top item if present, otherwise none and set error (no preconditions). boost::optional item() const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT( // Error if impossible. - this->empty() == (error() == underflow_error)); + // Error if impossible. + BOOST_CONTRACT_ASSERT(empty() == (error() == underflow_error)); // No error if possible. BOOST_CONTRACT_ASSERT(!empty() == !error()); }) @@ -86,20 +88,20 @@ public: // Error indicator set by various operations. error_code error() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return error_; } bool empty() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return stack_.empty(); } bool full() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return stack_.full(); } @@ -107,9 +109,9 @@ public: // Add x to top if capacity allows, otherwise set error (no preconditions). void put(T const& x) { - auto old_full = BOOST_CONTRACT_OLDOF(full()); - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_full = BOOST_CONTRACT_OLDOF(full()); + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Error if impossible. BOOST_CONTRACT_ASSERT(*old_full == (error() == overflow_error)); @@ -133,9 +135,10 @@ public: // Remove top item if possible, otherwise set error (no preconditions). void remove() { - auto old_empty = BOOST_CONTRACT_OLDOF(empty()); - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_empty = + BOOST_CONTRACT_OLDOF(empty()); + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Error if impossible. BOOST_CONTRACT_ASSERT(*old_empty == (error() == @@ -164,21 +167,21 @@ private: int main() { stack3 s(3); - BOOST_TEST_EQ(s.capacity(), 3); - BOOST_TEST_EQ(s.count(), 0); - BOOST_TEST(s.empty()); - BOOST_TEST(!s.full()); + assert(s.capacity() == 3); + assert(s.count() == 0); + assert(s.empty()); + assert(!s.full()); s.put(123); - BOOST_TEST(!s.empty()); - BOOST_TEST(!s.full()); - BOOST_TEST_EQ(*s.item(), 123); + assert(!s.empty()); + assert(!s.full()); + assert(*s.item() == 123); s.remove(); - BOOST_TEST(s.empty()); - BOOST_TEST(!s.full()); + assert(s.empty()); + assert(!s.full()); - return boost::report_errors(); + return 0; } //] diff --git a/example/meyer97/stack4.e b/example/meyer97/stack4.e index d27b075..0f9b0b8 100644 --- a/example/meyer97/stack4.e +++ b/example/meyer97/stack4.e @@ -1,58 +1,147 @@ //[meyer97_stack4_e --- File: stack4.e +-- Extra spaces, newlines, etc. for visual alignment with this library code. + + + + indexing destription: "Dispenser with LIFO access policy and a fixed max capacity." -class interface STACK4[G] creation make +class interface STACK4[G] creation make -- Interface only (no implementation). + + + + + + invariant count_non_negative: count >= 0 count_bounded: count <= capacity empty_if_no_elements: empty = (count = 0) + + feature -- Initialization. -- Allocate stack for a maximum of n elements. - make ( n : INTEGER ) is + make(n: INTEGER) is require non_negative_capacity: n >= 0 ensure capacity_set: capacity = n end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + feature -- Access. -- Max number of stack elements. - capacity : INTEGER + capacity: INTEGER + + + + -- Number of stack elements. - count : INTEGER + count: INTEGER + + + + -- Top element - item : G is + item: G is require not_empty: not empty -- i.e., count > 0 end + + + + + feature -- Status report. -- Is stack empty? - empty : BOOLEAN is + empty: BOOLEAN is ensure empty_definition: result = (count = 0) end + + + + + + + -- Is stack full? - full : BOOLEAN is + full: BOOLEAN is ensure full_definition: result = (count = capacity) end + + + + + + + feature -- Element change. -- Add x on top. - put ( x : G ) is + put(x: G) is require not_full: not full ensure @@ -61,6 +150,13 @@ feature -- Element change. one_more_item: count = old count + 1 end + + + + + + + -- Remove top element. remove is require @@ -71,6 +167,18 @@ feature -- Element change. end + + + + + + + + + + end -- class interface STACK4 + +-- End. //] diff --git a/example/meyer97/stack4.hpp b/example/meyer97/stack4.hpp index a187fa5..19790b1 100644 --- a/example/meyer97/stack4.hpp +++ b/example/meyer97/stack4.hpp @@ -1,5 +1,5 @@ -//[meyer97_stack4_header +//[meyer97_stack4 // File: stack4.hpp #ifndef STACK4_HPP_ #define STACK4_HPP_ @@ -12,7 +12,7 @@ class stack4 #define BASES private boost::contract::constructor_precondition > : BASES { -public: + friend boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES @@ -22,6 +22,7 @@ public: BOOST_CONTRACT_ASSERT(empty() == (count() == 0)); // Empty if no item. } +public: /* Initialization */ // Allocate static from a maximum of n items. @@ -30,7 +31,7 @@ public: BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative capacity. }) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(capacity() == n); // Capacity set. }) @@ -43,7 +44,7 @@ public: // Deep copy via constructor. /* implicit */ stack4(stack4 const& other) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(capacity() == other.capacity()); BOOST_CONTRACT_ASSERT(count() == other.count()); @@ -59,7 +60,7 @@ public: // Deep copy via assignment. stack4& operator=(stack4 const& other) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(capacity() == other.capacity()); BOOST_CONTRACT_ASSERT(count() == other.count()); @@ -77,7 +78,8 @@ public: // Destroy this stack. virtual ~stack4() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); delete[] array_; } @@ -85,19 +87,21 @@ public: // Max number of stack items. int capacity() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return capacity_; } // Number of stack items. int count() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return count_; } // Top item. T const& item() const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); // Not empty (count > 0). }) @@ -111,7 +115,7 @@ public: // Is stack empty? bool empty() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Empty definition. BOOST_CONTRACT_ASSERT(result == (count() == 0)); @@ -124,7 +128,7 @@ public: // Is stack full? bool full() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT( // Full definition. result == (count() == capacity())); @@ -138,8 +142,8 @@ public: // Add x on top. void put(T const& x) { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!full()); // Not full. }) @@ -155,8 +159,8 @@ public: // Remove top item. void remove() { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); // Not empty (count > 0). }) diff --git a/example/meyer97/stack4_main.cpp b/example/meyer97/stack4_main.cpp index 3d3d893..41ae023 100644 --- a/example/meyer97/stack4_main.cpp +++ b/example/meyer97/stack4_main.cpp @@ -1,26 +1,25 @@ //[meyer97_stack4_main -// File: stack4_main.cpp #include "stack4.hpp" -#include +#include int main() { stack4 s(3); - BOOST_TEST_EQ(s.capacity(), 3); - BOOST_TEST_EQ(s.count(), 0); - BOOST_TEST(s.empty()); - BOOST_TEST(!s.full()); + assert(s.capacity() == 3); + assert(s.count() == 0); + assert(s.empty()); + assert(!s.full()); s.put(123); - BOOST_TEST(!s.empty()); - BOOST_TEST(!s.full()); - BOOST_TEST_EQ(s.item(), 123); + assert(!s.empty()); + assert(!s.full()); + assert(s.item() == 123); s.remove(); - BOOST_TEST(s.empty()); - BOOST_TEST(!s.full()); + assert(s.empty()); + assert(!s.full()); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/counter/counter.hpp b/example/mitchell02/counter/counter.hpp index 53779c3..ca0f9d3 100644 --- a/example/mitchell02/counter/counter.hpp +++ b/example/mitchell02/counter/counter.hpp @@ -10,29 +10,32 @@ class counter #define BASES public subject : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES +public: /* Creation */ // Construct counter with specified value. - explicit counter(int _value = 10) : value_(_value) { - auto c = boost::contract::constructor(this) + explicit counter(int a_value = 10) : value_(a_value) { + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(value() == _value); // Value set. + BOOST_CONTRACT_ASSERT(value() == a_value); // Value set. }) ; } // Destroy counter. - virtual ~counter() { auto c = boost::contract::destructor(this); } + virtual ~counter() { + boost::contract::guard c = boost::contract::destructor(this); + } /* Queries */ // Current counter value. int value() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return value_; } @@ -40,8 +43,8 @@ public: // Decrement counter value. void decrement() { - auto old_value = BOOST_CONTRACT_OLDOF(value()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_value = BOOST_CONTRACT_OLDOF(value()); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(value() == *old_value - 1); // Decrement. }) diff --git a/example/mitchell02/counter/decrement_button.hpp b/example/mitchell02/counter/decrement_button.hpp index 1c4b097..7d398c5 100644 --- a/example/mitchell02/counter/decrement_button.hpp +++ b/example/mitchell02/counter/decrement_button.hpp @@ -14,32 +14,38 @@ class decrement_button private boost::noncopyable : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + BOOST_CONTRACT_OVERRIDES(on_bn_clicked, up_to_date_with_subject, update); +public: /* Creation */ - explicit decrement_button(counter& _counter) : counter_(_counter) { - auto c = boost::contract::constructor(this) + explicit decrement_button(counter& a_counter) : counter_(a_counter) { + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { // Enable iff positive value. - BOOST_CONTRACT_ASSERT(enabled() == (_counter.value() > 0)); + BOOST_CONTRACT_ASSERT(enabled() == (a_counter.value() > 0)); }) ; counter_.attach(this); } // Destroy button. - virtual ~decrement_button() { auto c = boost::contract::destructor(this); } + virtual ~decrement_button() { + boost::contract::guard c = boost::contract::destructor(this); + } /* Commands */ virtual void on_bn_clicked(boost::contract::virtual_* v = 0) /* override */ { - auto old_value = BOOST_CONTRACT_OLDOF(v, counter_.value()); - auto c = boost::contract::public_function( - v, &decrement_button::on_bn_clicked, this) + boost::contract::old_ptr old_value = + BOOST_CONTRACT_OLDOF(v, counter_.value()); + boost::contract::guard c = boost::contract::public_function< + override_on_bn_clicked + >(v, &decrement_button::on_bn_clicked, this) .postcondition([&] { // Counter decremented. BOOST_CONTRACT_ASSERT(counter_.value() == *old_value - 1); @@ -47,22 +53,20 @@ public: ; counter_.decrement(); } - BOOST_CONTRACT_OVERRIDE(on_bn_clicked) virtual bool up_to_date_with_subject(boost::contract::virtual_* v = 0) const /* override */ { bool result; - auto c = boost::contract::public_function< + boost::contract::guard c = boost::contract::public_function< override_up_to_date_with_subject >(v, result, &decrement_button::up_to_date_with_subject, this); return result = true; // For simplicity, assume always up-to-date. } - BOOST_CONTRACT_OVERRIDE(up_to_date_with_subject) virtual void update(boost::contract::virtual_* v = 0) /* override */ { - auto c = boost::contract::public_function( - v, &decrement_button::update, this) + boost::contract::guard c = boost::contract::public_function< + override_update>(v, &decrement_button::update, this) .postcondition([&] { // Enabled iff positive value. BOOST_CONTRACT_ASSERT(enabled() == (counter_.value() > 0)); @@ -72,7 +76,6 @@ public: if(counter_.value() == 0) disable(); else enable(); } - BOOST_CONTRACT_OVERRIDE(update); private: counter& counter_; diff --git a/example/mitchell02/counter/push_button.hpp b/example/mitchell02/counter/push_button.hpp index 906a59e..ee86b49 100644 --- a/example/mitchell02/counter/push_button.hpp +++ b/example/mitchell02/counter/push_button.hpp @@ -4,14 +4,17 @@ #define PUSH_BUTTON_HPP_ #include +#include class push_button { public: + // No inv and no bases so contracts optional if no pre, post, and override. + /* Creation */ // Create an enabled button. push_button() : enabled_(true) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(enabled()); // Enabled. }) @@ -19,13 +22,15 @@ public: } // Destroy button. - virtual ~push_button() { auto c = boost::contract::destructor(this); } + virtual ~push_button() { + boost::contract::guard c = boost::contract::destructor(this); + } /* Queries */ // If button is enabled. bool enabled() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return enabled_; } @@ -33,7 +38,7 @@ public: // Enable button. void enable() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(enabled()); // Enabled. }) @@ -44,7 +49,7 @@ public: // Disable button. void disable() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(!enabled()); // Disabled. }) @@ -61,11 +66,12 @@ private: }; void push_button::on_bn_clicked(boost::contract::virtual_* v) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(enabled()); // Enabled. }) ; + assert(false); } #endif // #include guard diff --git a/example/mitchell02/counter_main.cpp b/example/mitchell02/counter_main.cpp index 1f7185a..eca356c 100644 --- a/example/mitchell02/counter_main.cpp +++ b/example/mitchell02/counter_main.cpp @@ -3,7 +3,7 @@ #include "counter/counter.hpp" #include "counter/decrement_button.hpp" #include "observer/observer.hpp" -#include +#include int test_counter; @@ -11,43 +11,45 @@ class view_of_counter #define BASES public observer : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + BOOST_CONTRACT_OVERRIDES(up_to_date_with_subject, update) +public: /* Creation */ // Create view associated with given counter. - explicit view_of_counter(counter& _counter) : counter_(_counter) { - auto c = boost::contract::constructor(this); + explicit view_of_counter(counter& a_counter) : counter_(a_counter) { + boost::contract::guard c = boost::contract::constructor(this); counter_.attach(this); - BOOST_TEST_EQ(counter_.value(), test_counter); + assert(counter_.value() == test_counter); } // Destroy view. - virtual ~view_of_counter() { auto c = boost::contract::destructor(this); } + virtual ~view_of_counter() { + boost::contract::guard c = boost::contract::destructor(this); + } /* Commands */ virtual bool up_to_date_with_subject(boost::contract::virtual_* v = 0) const /* override */ { bool result; - auto c = boost::contract::public_function< + boost::contract::guard c = boost::contract::public_function< override_up_to_date_with_subject >(v, result, &view_of_counter::up_to_date_with_subject, this); return result = true; // For simplicity, assume always up-to-date. } - BOOST_CONTRACT_OVERRIDE(up_to_date_with_subject) virtual void update(boost::contract::virtual_* v = 0) /* override */ { - auto c = boost::contract::public_function( - v, &view_of_counter::update, this); + boost::contract::guard c = boost::contract::public_function< + override_update>(v, &view_of_counter::update, this); - BOOST_TEST_EQ(counter_.value(), test_counter); + assert(counter_.value() == test_counter); } - BOOST_CONTRACT_OVERRIDE(update) private: counter& counter_; @@ -58,13 +60,13 @@ int main() { view_of_counter view(cnt); decrement_button dec(cnt); - BOOST_TEST(dec.enabled()); + assert(dec.enabled()); test_counter--; dec.on_bn_clicked(); - BOOST_TEST(!dec.enabled()); + assert(!dec.enabled()); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/courier.cpp b/example/mitchell02/courier.cpp index 368e8d1..9bea576 100644 --- a/example/mitchell02/courier.cpp +++ b/example/mitchell02/courier.cpp @@ -1,8 +1,8 @@ //[mitchell02_courier #include -#include #include +#include struct package { double weight_kg; @@ -28,7 +28,7 @@ class courier #define BASES private boost::contract::constructor_precondition : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES @@ -42,6 +42,7 @@ public: BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= min_insurance_usd); } +public: static double min_insurance_usd; /* Creation */ @@ -54,19 +55,22 @@ public: }), insurance_cover_usd_(_insurance_cover_usd) { - auto c = boost::contract::constructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::constructor(this); } // Destroy courier. virtual ~courier() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Queries */ // Return insurance cover. double insurance_cover_usd() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return insurance_cover_usd_; } @@ -78,7 +82,7 @@ public: std::string const& destination, boost::contract::virtual_* v = 0 ) { - auto c = boost::contract::public_function(v, this) + boost::contract::guard c = boost::contract::public_function(v, this) .precondition([&] { // Within max weight of this delivery. BOOST_CONTRACT_ASSERT(package_delivery.weight_kg < 5.0); @@ -109,9 +113,10 @@ class different_courier different_courier>, public courier : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. #undef BASES + BOOST_CONTRACT_OVERRIDE(deliver) static void static_invariant() { BOOST_CONTRACT_ASSERT( // Better insurance amount. @@ -123,6 +128,7 @@ public: BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= different_insurance_usd); } +public: static double different_insurance_usd; /* Creation */ @@ -136,12 +142,14 @@ public: }), courier(insurance_cover_usd) { - auto c = boost::contract::constructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::constructor(this); } // Destroy courier. virtual ~different_courier() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Commands */ @@ -151,9 +159,9 @@ public: std::string const& destination, boost::contract::virtual_* v = 0 ) /* override */ { - auto c = boost::contract::public_function( - v, &different_courier::deliver, this, package_delivery, destination - ) + boost::contract::guard c = boost::contract::public_function< + override_deliver + >(v, &different_courier::deliver, this, package_delivery, destination) .precondition([&] { // Package can weight more (weaker precondition). BOOST_CONTRACT_ASSERT(package_delivery.weight_kg <= 8.0); @@ -170,7 +178,6 @@ public: // Delivery takes 0.5 hours. package_delivery.delivered_hour = package_delivery.accepted_hour + 0.5; } - BOOST_CONTRACT_OVERRIDE(deliver) }; double different_courier::different_insurance_usd = 20.0e+6; @@ -179,14 +186,14 @@ int main() { package cups(3.6, "store"); courier c; c.deliver(cups, "home"); - BOOST_TEST_EQ(cups.location, "home"); + assert(cups.location == "home"); package desk(7.2, "store"); different_courier dc; dc.deliver(desk, "office"); - BOOST_TEST_EQ(desk.location, "office"); + assert(desk.location == "office"); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/customer_manager.cpp b/example/mitchell02/customer_manager.cpp index 4c76765..f40268a 100644 --- a/example/mitchell02/customer_manager.cpp +++ b/example/mitchell02/customer_manager.cpp @@ -1,13 +1,15 @@ //[mitchell02_customer_manager #include -#include #include #include #include +#include // Basic customer information. struct customer_info { + friend class customer_manager; + typedef std::string identifier; identifier id; @@ -19,43 +21,47 @@ private: std::string name_; std::string address_; std::string birthday_; - - friend class customer_manager; }; // Manage customers. class customer_manager { -public: + friend class boost::contract::access; + void invariant() const { BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } +public: /* Creation */ customer_manager() { - auto c = boost::contract::constructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::constructor(this); } virtual ~customer_manager() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Basic Queries */ int count() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return customers_.size(); } bool id_active(customer_info::identifier const& id) const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return customers_.find(id) != customers_.cend(); } /* Derived Queries */ std::string const& name_for(customer_info::identifier const& id) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(id_active(id)); // Active. }) @@ -68,8 +74,8 @@ public: /* Commands */ void add(customer_info const& info) { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { // Not already active. BOOST_CONTRACT_ASSERT(!id_active(info.id)); @@ -83,9 +89,9 @@ public: customers_.insert(std::make_pair(info.id, customer(info))); } - void set_name( - customer_info::identifier const& id, std::string const& name) { - auto c = boost::contract::public_function(this) + void set_name(customer_info::identifier const& id, + std::string const& name) { + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(id_active(id)); // Already active. }) @@ -114,15 +120,13 @@ private: int main() { customer_manager m; - customer_info const js("john_smith_123"); m.add(js); m.set_name(js.id, "John Smith"); - BOOST_TEST_EQ(m.name_for(js.id), "John Smith"); - BOOST_TEST_EQ(m.count(), 1); - BOOST_TEST(m.id_active(js.id)); - - return boost::report_errors(); + assert(m.name_for(js.id) == "John Smith"); + assert(m.count() == 1); + assert(m.id_active(js.id)); + return 0; } //] diff --git a/example/mitchell02/dictionary.cpp b/example/mitchell02/dictionary.cpp index e1f0b04..64c36ab 100644 --- a/example/mitchell02/dictionary.cpp +++ b/example/mitchell02/dictionary.cpp @@ -1,22 +1,24 @@ //[mitchell02_dictionary #include -#include #include #include +#include template class dictionary { -public: + friend class boost::contract::access; + void invariant() const { BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } +public: /* Creation */ // Create empty dictionary. dictionary() { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == 0); // Empty. }) @@ -25,21 +27,23 @@ public: // Destroy dictionary. ~dictionary() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Basic Queries */ // Number of key entries. int count() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return items_.size(); } // Has entry for key? bool has(K const& key) const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Empty has no key. if(count() == 0) BOOST_CONTRACT_ASSERT(!result); @@ -51,7 +55,7 @@ public: // Value for a given key. T const& value_for(K const& key) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(has(key)); // Has key. }) @@ -65,8 +69,8 @@ public: // Add value of a given key. void put(K const& key, T const& value) { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!has(key)); // Has not key already. }) @@ -83,8 +87,8 @@ public: // Remove value for given key. void remove(K const& key) { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(has(key)); // Has key. }) @@ -105,15 +109,15 @@ int main() { std::string const js = "John Smith"; dictionary ages; - BOOST_TEST(!ages.has(js)); + assert(!ages.has(js)); ages.put(js, 23); - BOOST_TEST_EQ(ages.value_for(js), 23); + assert(ages.value_for(js) == 23); ages.remove(js); - BOOST_TEST_EQ(ages.count(), 0); + assert(ages.count() == 0); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/name_list.cpp b/example/mitchell02/name_list.cpp index 9a02582..1a3ba90 100644 --- a/example/mitchell02/name_list.cpp +++ b/example/mitchell02/name_list.cpp @@ -1,23 +1,25 @@ //[mitchell02_name_list #include -#include #include #include #include +#include // List of names. class name_list { -public: + friend class boost::contract::access; + void invariant() const { BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } +public: /* Creation */ // Create an empty list. name_list() { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == 0); // Empty list. }) @@ -26,21 +28,23 @@ public: // Destroy list. virtual ~name_list() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Basic Queries */ // Number of names in list. int count() const { - auto c = boost::contract::public_function(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return names_.size(); } // Is name in list? bool has(std::string const& name) const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // If empty, has not. if(count() == 0) BOOST_CONTRACT_ASSERT(!result); @@ -56,9 +60,11 @@ public: // Add name to list, if name not already in list. virtual void put(std::string const& name, boost::contract::virtual_* v = 0) { - auto old_has_name = BOOST_CONTRACT_OLDOF(v, has(name)); - auto old_count = BOOST_CONTRACT_OLDOF(v, count()); - auto c = boost::contract::public_function(v, this) + boost::contract::old_ptr old_has_name = + BOOST_CONTRACT_OLDOF(v, has(name)); + boost::contract::old_ptr old_count = + BOOST_CONTRACT_OLDOF(v, count()); + boost::contract::guard c = boost::contract::public_function(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(!has(name)); // Not already in list. }) @@ -81,19 +87,23 @@ class relaxed_name_list #define BASES public name_list : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. #undef BASES + BOOST_CONTRACT_OVERRIDE(put); +public: /* Commands */ // Add name to list, or do nothing if name already in list (relaxed). void put(std::string const& name, boost::contract::virtual_* v = 0) /* override */ { - auto old_has_name = BOOST_CONTRACT_OLDOF(v, has(name)); - auto old_count = BOOST_CONTRACT_OLDOF(v, count()); - auto c = boost::contract::public_function( - v, &relaxed_name_list::put, this, name) + boost::contract::old_ptr old_has_name = + BOOST_CONTRACT_OLDOF(v, has(name)); + boost::contract::old_ptr old_count = + BOOST_CONTRACT_OLDOF(v, count()); + boost::contract::guard c = boost::contract::public_function< + override_put>(v, &relaxed_name_list::put, this, name) .precondition([&] { // Relax inherited preconditions. BOOST_CONTRACT_ASSERT(has(name)); // Already in list. }) @@ -107,7 +117,6 @@ public: if(!has(name)) name_list::put(name); // Else, do nothing. } - BOOST_CONTRACT_OVERRIDE(put); }; int main() { @@ -115,15 +124,15 @@ int main() { relaxed_name_list rl; rl.put(js); - BOOST_TEST(rl.has(js)); + assert(rl.has(js)); rl.put(js); // OK, relaxed contracts allow calling this again (do nothing). name_list nl; nl.put(js); - BOOST_TEST(nl.has(js)); + assert(nl.has(js)); // nl.put(js); // Error, contracts do not allow calling this again. - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/observer/observer.hpp b/example/mitchell02/observer/observer.hpp index dad63c3..4cdaefa 100644 --- a/example/mitchell02/observer/observer.hpp +++ b/example/mitchell02/observer/observer.hpp @@ -4,17 +4,23 @@ #define OBSERVER_HPP_ #include +#include // Observer. class observer { + friend class subject; public: - // No inv so contracts could have been omitted when also no pre/post... + // No inv and no bases so contracts optional if no pre, post, and override. /* Creation */ - observer() { auto c = boost::contract::constructor(this); } + observer() { + boost::contract::guard c = boost::contract::constructor(this); + } - virtual ~observer() { auto c = boost::contract::destructor(this); } + virtual ~observer() { + boost::contract::guard c = boost::contract::destructor(this); + } /* Commands */ @@ -24,22 +30,21 @@ public: // Update this observer. virtual void update(boost::contract::virtual_* v = 0) = 0; - -private: - friend class subject; }; bool observer::up_to_date_with_subject(boost::contract::virtual_* v) const { - auto c = boost::contract::public_function(this); - return false; // Never reached. + boost::contract::guard c = boost::contract::public_function(v, this); + assert(false); + return false; } void observer::update(boost::contract::virtual_* v) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(v, this) .postcondition([&] { BOOST_CONTRACT_ASSERT(up_to_date_with_subject()); // Up-to-date. }) ; + assert(false); } #endif // #include guard diff --git a/example/mitchell02/observer/subject.hpp b/example/mitchell02/observer/subject.hpp index d42d290..1fb76fd 100644 --- a/example/mitchell02/observer/subject.hpp +++ b/example/mitchell02/observer/subject.hpp @@ -16,30 +16,34 @@ // Subject for observer design pattern. class subject { -public: + friend class boost::contract::access; + void invariant() const { if(O_N <= COMPLEXITY_MAX) { BOOST_CONTRACT_ASSERT(all_observers_valid(observers())); // Valid. } } +public: /* Creation */ // Construct subject with no observer. subject() { - auto c = boost::contract::constructor(this); // Check invariant. + // Check invariant. + boost::contract::guard c = boost::contract::constructor(this); } // Destroy subject. virtual ~subject() { - auto c = boost::contract::destructor(this); // Check invariant. + // Check invariant. + boost::contract::guard c = boost::contract::destructor(this); } /* Queries */ // If given object is attached. bool attached(observer const* ob) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(ob); // Not null. }) @@ -53,8 +57,9 @@ public: // Attach given object as an observer. void attach(observer* ob) { - auto old_observers = BOOST_CONTRACT_OLDOF(observers()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr > old_observers = + BOOST_CONTRACT_OLDOF(observers()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(ob); // Not null. BOOST_CONTRACT_ASSERT(!attached(ob)); // Not already attached. @@ -91,7 +96,8 @@ protected: // Update all attached observers. void notify() { - auto c = boost::contract::function() + // Protected members use `function` (no inv and no subcontracting). + boost::contract::guard c = boost::contract::function() .postcondition([&] { if(O_N <= COMPLEXITY_MAX) { // All updated. @@ -125,7 +131,8 @@ private: std::vector const& new_obs, observer const* ob ) { - auto c = boost::contract::function() + // Private members use `function` (no inv and no subcontracting). + boost::contract::guard c = boost::contract::function() .precondition([&] { BOOST_CONTRACT_ASSERT(ob); // Not null. }) diff --git a/example/mitchell02/observer_main.cpp b/example/mitchell02/observer_main.cpp index d458d97..2478819 100644 --- a/example/mitchell02/observer_main.cpp +++ b/example/mitchell02/observer_main.cpp @@ -3,37 +3,40 @@ #include "observer/observer.hpp" #include "observer/subject.hpp" #include -#include +#include -int test_state; // For unit testing only. +int test_state; // For testing only. // Implement an actual subject. class concrete_subject #define BASES public subject : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. #undef BASES +public: typedef int state; // Some state being observed. concrete_subject() : state_() { - auto c = boost::contract::constructor(this); + boost::contract::guard c = boost::contract::constructor(this); } - ~concrete_subject() { auto c = boost::contract::destructor(this); } + ~concrete_subject() { + boost::contract::guard c = boost::contract::destructor(this); + } void set_state(state const& new_state) { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); state_ = new_state; - BOOST_TEST_EQ(state_, test_state); + assert(state_ == test_state); notify(); // Notify all observers. } state get_state() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return state_; } @@ -46,39 +49,41 @@ class concrete_observer #define BASES public observer : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. #undef BASES + BOOST_CONTRACT_OVERRIDES(up_to_date_with_subject, update) +public: // Create concrete observer. explicit concrete_observer(concrete_subject const& subj) : subject_(subj), observed_state_() { - auto c = boost::contract::constructor(this); // Check subcontracts. + boost::contract::guard c = boost::contract::constructor(this); } - ~concrete_observer() { auto c = boost::contract::destructor(this); } + ~concrete_observer() { + boost::contract::guard c = boost::contract::destructor(this); + } // Implement base virtual functions. bool up_to_date_with_subject(boost::contract::virtual_* v = 0) const /* override */ { bool result; - auto c = boost::contract::public_function< + boost::contract::guard c = boost::contract::public_function< override_up_to_date_with_subject >(v, result, &concrete_observer::up_to_date_with_subject, this); return result = true; // For simplicity, assume always up-to-date. } - BOOST_CONTRACT_OVERRIDE(up_to_date_with_subject) void update(boost::contract::virtual_* v = 0) /* override */ { - auto c = boost::contract::public_function( - v, &concrete_observer::update, this); + boost::contract::guard c = boost::contract::public_function< + override_update>(v, &concrete_observer::update, this); observed_state_ = subject_.get_state(); - BOOST_TEST_EQ(observed_state_, test_state); + assert(observed_state_ == test_state); } - BOOST_CONTRACT_OVERRIDE(update) private: concrete_subject const& subject_; @@ -93,7 +98,7 @@ int main() { subj.set_state(test_state = 123); subj.set_state(test_state = 456); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/simple_queue.cpp b/example/mitchell02/simple_queue.cpp index 07cc4f6..77b70de 100644 --- a/example/mitchell02/simple_queue.cpp +++ b/example/mitchell02/simple_queue.cpp @@ -2,8 +2,8 @@ //[mitchell02_simple_queue #include #include -#include #include +#include // Disable selected expensive assertion checks and old value copies. #define O_1 0 // O(1): constant complexity (default). @@ -16,7 +16,8 @@ class simple_queue simple_queue > : BASES { -public: + friend class boost::contract::access; + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES @@ -24,27 +25,30 @@ public: BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } +public: /* Creation */ // Create empty queue. - explicit simple_queue(int _capacity) : + explicit simple_queue(int a_capacity) : boost::contract::constructor_precondition([&] { - BOOST_CONTRACT_ASSERT(_capacity > 0); // Positive capacity. + BOOST_CONTRACT_ASSERT(a_capacity > 0); // Positive capacity. }) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(capacity() == _capacity); // Capacity set. - BOOST_CONTRACT_ASSERT(this->is_empty()); // Empty. + // Capacity set. + BOOST_CONTRACT_ASSERT(capacity() == a_capacity); + BOOST_CONTRACT_ASSERT(is_empty()); // Empty. }) ; - items_.reserve(_capacity); + items_.reserve(a_capacity); } // Destroy queue. virtual ~simple_queue() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Basic Queries */ @@ -52,15 +56,15 @@ public: // Items in queue (in their order). // (Somewhat exposes implementation but allows to check more contracts.) std::vector const& items() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return items_; } // Max number of items queue can hold. int capacity() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return items_.capacity(); } @@ -69,7 +73,7 @@ public: // Number of items. int count() const { int result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Return items count. BOOST_CONTRACT_ASSERT(result == int(items().size())); @@ -82,7 +86,7 @@ public: // Item at head. T const& head() const { boost::optional result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!is_empty()); // Not empty. }) @@ -98,7 +102,7 @@ public: // If queue contains no item. bool is_empty() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Consistent with count. BOOST_CONTRACT_ASSERT(result == (count() == 0)); @@ -111,7 +115,7 @@ public: // If queue as no room for another item. bool is_full() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT( // Consistent with size and capacity. result == (capacity() == int(items().size()))); @@ -126,19 +130,16 @@ public: // Remove head itme and shift all other items. void remove() { // Expensive all_equal postcond. and old_items copy might be skipped. - boost::shared_ptr const> old_items; + boost::contract::old_ptr > old_items; if(O_N <= COMPLEXITY_MAX) old_items = BOOST_CONTRACT_OLDOF(items()); - - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!is_empty()); // Not empty. }) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec. - if(O_N <= COMPLEXITY_MAX) { - all_equal(items(), *old_items, /* shifted = */ 1); - } + if(old_items) all_equal(items(), *old_items, /* shifted = */ 1); }) ; @@ -148,11 +149,10 @@ public: // Add item to tail. void put(T const& item) { // Expensive all_equal postcond. and old_items copy might be skipped. - boost::shared_ptr const> old_items; + boost::contract::old_ptr > old_items; if(O_N <= COMPLEXITY_MAX) old_items = BOOST_CONTRACT_OLDOF(items()); - - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count() < capacity()); // Room for add. }) @@ -160,7 +160,7 @@ public: BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. // Second to last item. BOOST_CONTRACT_ASSERT(items().at(count() - 1) == item); - if(O_N <= COMPLEXITY_MAX) all_equal(items(), *old_items); + if(old_items) all_equal(items(), *old_items); }) ; @@ -171,7 +171,7 @@ private: // Contract helper. static bool all_equal(std::vector const& left, std::vector const& right, unsigned offset = 0) { - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .precondition([&] { // Correct offset. BOOST_CONTRACT_ASSERT(right.size() == left.size() + offset); @@ -191,21 +191,21 @@ int main() { simple_queue q(10); q.put(123); q.put(456); - - BOOST_TEST_EQ(q.capacity(), 10); - BOOST_TEST_EQ(q.head(), 123); - - BOOST_TEST(!q.is_empty()); - BOOST_TEST(!q.is_full()); + + assert(q.capacity() == 10); + assert(q.head() == 123); + + assert(!q.is_empty()); + assert(!q.is_full()); std::vector const& items = q.items(); - BOOST_TEST_EQ(items.at(0), 123); - BOOST_TEST_EQ(items.at(1), 456); + assert(items.at(0) == 123); + assert(items.at(1) == 456); q.remove(); - BOOST_TEST_EQ(q.count(), 1); + assert(q.count() == 1); - return boost::report_errors(); + return 0; } //] diff --git a/example/mitchell02/stack.cpp b/example/mitchell02/stack.cpp index 4868d6f..257f290 100644 --- a/example/mitchell02/stack.cpp +++ b/example/mitchell02/stack.cpp @@ -2,21 +2,23 @@ //[mitchell02_stack #include #include -#include #include +#include template class stack { -public: + friend class boost::contract::access; + void invariant() const { BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } +public: /* Creation */ // Create empty stack. stack() { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == 0); // Empty. }) @@ -25,21 +27,22 @@ public: // Destroy stack. virtual ~stack() { - auto c = boost::contract::destructor(this); // Check invariants. + // Check invariants. + boost::contract::guard c = boost::contract::destructor(this); } /* Basic Queries */ // Number of items. int count() const { - auto c = boost::contract::public_function(this); // Check invariants. - + // Check invariants. + boost::contract::guard c = boost::contract::public_function(this); return items_.size(); } // Item at index in [1, count()] (as in Eiffel). T const& item_at(int index) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(index > 0); // Positive index. BOOST_CONTRACT_ASSERT(index <= count()); // Index within count. @@ -54,7 +57,7 @@ public: // If no items. bool is_empty() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { // Consistent with count. BOOST_CONTRACT_ASSERT(result == (count() == 0)); @@ -67,7 +70,7 @@ public: // Top item. T const& item() const { boost::optional result; // Avoid extra construction of T. - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count() > 0); // Not empty. }) @@ -84,8 +87,8 @@ public: // Push item to the top. void put(T const& new_item) { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. BOOST_CONTRACT_ASSERT(item() == new_item); // Item set. @@ -97,8 +100,8 @@ public: // Pop top item. void remove() { - auto old_count = BOOST_CONTRACT_OLDOF(count()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count() > 0); // Not empty. }) @@ -116,15 +119,15 @@ private: int main() { stack s; - BOOST_TEST_EQ(s.count(), 0); + assert(s.count() == 0); s.put(123); - BOOST_TEST_EQ(s.item(), 123); + assert(s.item() == 123); s.remove(); - BOOST_TEST(s.is_empty()); + assert(s.is_empty()); - return boost::report_errors(); + return 0; } //] diff --git a/example/n1962/circle.cpp b/example/n1962/circle.cpp index db01984..c3805e4 100644 --- a/example/n1962/circle.cpp +++ b/example/n1962/circle.cpp @@ -1,57 +1,73 @@ //[n1962_circle #include -#include #include class shape { public: virtual ~shape() {} - virtual int compute_area(boost::contract::virtual_* v = 0) const = 0; + virtual unsigned compute_area(boost::contract::virtual_* v = 0) const = 0; }; -int shape::compute_area(boost::contract::virtual_* v) const { - int result; - auto c = boost::contract::public_function(v, result, this) +unsigned shape::compute_area(boost::contract::virtual_* v) const { + unsigned result; + boost::contract::guard c = boost::contract::public_function(v, result, this) .postcondition([&] (int const& result) { BOOST_CONTRACT_ASSERT(result > 0); }) ; - assert(false); return result = -1; // Never gets here. + assert(false); + return result = 0; } class circle #define BASES public shape : BASES { -public: + friend class boost::contract::access; typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + BOOST_CONTRACT_OVERRIDE(compute_area); - int radius; // Make sure to set this... +public: static int const pi = 3; // Truncated to int from 3.14... - virtual int compute_area(boost::contract::virtual_* v = 0) - const /* override */ { - int result; - auto c = boost::contract::public_function( - v, result, &circle::compute_area, this) - .postcondition([&] (int const& result) { - BOOST_CONTRACT_ASSERT(result == pi * radius * radius); + explicit circle(unsigned a_radius) : radius_(a_radius) { + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(radius() == a_radius); + }) + ; + } + + virtual unsigned compute_area(boost::contract::virtual_* v = 0) const + /* override */ { + unsigned result; + boost::contract::guard c = boost::contract::public_function< + override_compute_area>(v, result, &circle::compute_area, this) + .postcondition([&] (unsigned const& result) { + BOOST_CONTRACT_ASSERT(result == pi * radius() * radius()); }) ; - return result = pi * radius * radius; + return result = pi * radius() * radius(); } - BOOST_CONTRACT_OVERRIDE(compute_area); + + unsigned radius() const { + boost::contract::guard c = boost::contract::public_function(this); + return radius_; + } + +private: + unsigned radius_; }; int main() { - circle c; - c.radius = 2; - BOOST_TEST_EQ(c.compute_area(), 12); - return boost::report_errors(); + circle c(2); + assert(c.radius() == 2); + assert(c.compute_area() == 12); + return 0; } //] diff --git a/example/n1962/equal.cpp b/example/n1962/equal.cpp index b9cf03e..e3626b4 100644 --- a/example/n1962/equal.cpp +++ b/example/n1962/equal.cpp @@ -1,7 +1,7 @@ //[n1962_equal #include -#include +#include // Forward declaration because == and != contracts use one another's function. template @@ -10,7 +10,7 @@ bool operator==(T const& left, T const& right); template bool operator!=(T const& left, T const& right) { bool result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .postcondition([&] { BOOST_CONTRACT_ASSERT(result == !(left == right)); }) @@ -22,7 +22,7 @@ bool operator!=(T const& left, T const& right) { template bool operator==(T const& left, T const& right) { bool result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .postcondition([&] { BOOST_CONTRACT_ASSERT(result == !(left != right)); }) @@ -37,10 +37,10 @@ int main() { number n; n.value = 123; - BOOST_TEST_EQ(n == n, true); // Explicitly call operator==. - BOOST_TEST_EQ(n != n, false); // Explicitly call operator!=. + assert((n == n) == true); // Explicitly call operator==. + assert((n != n) == false); // Explicitly call operator!=. - return boost::report_errors(); + return 0; } //] diff --git a/example/n1962/factorial.cpp b/example/n1962/factorial.cpp index e270082..84c85f0 100644 --- a/example/n1962/factorial.cpp +++ b/example/n1962/factorial.cpp @@ -1,7 +1,7 @@ //[n1962_factorial #include -#include +#include // Assertion complexity classified relative their function body complexity. #define O_LESS_THAN_BODY 0 @@ -11,7 +11,7 @@ int factorial(int n ) { int result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .precondition([&] { BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative natural number. BOOST_CONTRACT_ASSERT(n <= 12); // Max function input. @@ -25,7 +25,7 @@ int factorial(int n ) { // (same as the function body) so assertion can be selectively // disabled by setting COMPLEXITY_MAX. if(O_SAME_AS_BODY <= COMPLEXITY_MAX) { - // Assertion automatically disable within other assertions. + // Assertions automatically disabled in other assertions. // Therefore, this postcondition can recursively call the // function without causing infinite recursion. BOOST_CONTRACT_ASSERT(n * factorial(n - 1)); @@ -38,8 +38,8 @@ int factorial(int n ) { } int main() { - BOOST_TEST_EQ(factorial(4), 24); - return boost::report_errors(); + assert(factorial(4) == 24); + return 0; } //] diff --git a/example/n1962/sqrt.cpp b/example/n1962/sqrt.cpp index 9d3c090..6724eed 100644 --- a/example/n1962/sqrt.cpp +++ b/example/n1962/sqrt.cpp @@ -1,12 +1,12 @@ //[n1962_sqrt #include -#include #include +#include double mysqrt(double x, double precision = 1e-6) { double result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .precondition([&] { BOOST_CONTRACT_ASSERT(x >= 0.0); }) @@ -20,8 +20,8 @@ double mysqrt(double x, double precision = 1e-6) { int main() { double const precision = 1e-6; - BOOST_TEST(fabs(mysqrt(4.0, precision) - 2.0) <= precision); - return boost::report_errors(); + assert(fabs(mysqrt(4.0, precision) - 2.0) <= precision); + return 0; } //] diff --git a/example/n1962/sqrt.d b/example/n1962/sqrt.d index 9fe53d9..435fd5a 100644 --- a/example/n1962/sqrt.d +++ b/example/n1962/sqrt.d @@ -1,17 +1,17 @@ //[n1962_sqrt_d -// Extra newlines, etc. used to align text with this library code. +// Extra spaces, newlines, etc. for visual alignment with this library code. - -real mysqrt ( real x ) // No default parameters in D. - in { assert(x >= 0); } - out(root) { - - assert(std.math.fabs(root * root - x) <= 1e6); +real mysqrt(real x) + in { + assert(x >= 0.0); } -body { + out(result) { + assert(std.math.fabs(result * result - x) <= 1e-6); + } +body { return std.math.sqrt(x); } @@ -20,5 +20,8 @@ body { + + +// End. //] diff --git a/example/n1962/sum.cpp b/example/n1962/sum.cpp index 19ae894..8ce5958 100644 --- a/example/n1962/sum.cpp +++ b/example/n1962/sum.cpp @@ -1,11 +1,11 @@ //[n1962_sum #include -#include +#include int sum(int count, int* array) { int result; - auto c = boost::contract::function() + boost::contract::guard c = boost::contract::function() .precondition([&] { BOOST_CONTRACT_ASSERT(count % 4 == 0); }) @@ -18,8 +18,8 @@ int sum(int count, int* array) { int main() { int a[4] = {1, 2, 3, 4}; - BOOST_TEST_EQ(sum(4, a), 10); - return boost::report_errors(); + assert(sum(4, a) == 10); + return 0; } //] diff --git a/example/n1962/vector.cpp b/example/n1962/vector.cpp index 0311a13..d151eb9 100644 --- a/example/n1962/vector.cpp +++ b/example/n1962/vector.cpp @@ -5,15 +5,14 @@ #include #include #include -#include #include #include #include #include +#include -// TODO: Is there any way around this? Probably not... -// This can be programmed directly at call site with C++14 generic lambdas. -struct all_of_equal { +// Could be programmed at call site with C++14 generic lambdas. +struct all_of_equal_to { typedef bool result_type; template @@ -22,40 +21,10 @@ struct all_of_equal { } }; -// TODO: Try if this is still the case with MSVC 2013... -// This is required on MSVC (which cannot always deduce lambda result type). -template -struct always_call { - typedef T result_type; - - explicit always_call(T const& r) : r_(r) {} - - result_type operator()(...) const { return r_; } - -private: - T r_; -}; -template -always_call always(T const& r) { return always_call(r); } - -// TODO: Fix all code below to use helpers above... - -template > +// STL vector requires T copyable but not equality comparable. +template > class vector { -public: - typedef typename std::vector::allocator_type allocator_type; - typedef typename std::vector::pointer pointer; - typedef typename std::vector::const_pointer const_pointer; - typedef typename std::vector::reference reference; - typedef typename std::vector::const_reference const_reference; - typedef typename std::vector::value_type value_type; - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; - typedef typename std::vector::size_type size_type; - typedef typename std::vector::difference_type difference_type; - typedef typename std::vector::reverse_iterator reverse_iterator; - typedef typename std::vector::const_reverse_iterator - const_reverse_iterator; + friend class boost::contract::access; void invariant() const { BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); @@ -65,56 +34,85 @@ public: BOOST_CONTRACT_ASSERT(capacity() <= max_size()); } +public: + typedef typename std::vector::allocator_type allocator_type; + typedef typename std::vector::pointer pointer; + typedef typename std::vector::const_pointer const_pointer; + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + typedef typename std::vector::value_type value_type; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::size_type size_type; + typedef typename std::vector::difference_type difference_type; + typedef typename std::vector::reverse_iterator + reverse_iterator; + typedef typename std::vector::const_reverse_iterator + const_reverse_iterator; + vector() : vect_() { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) ; } - explicit vector(Alloc const& allocator) : vect_(allocator) { - auto c = boost::contract::constructor(this) + explicit vector(Allocator const& alloc) : vect_(alloc) { + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(empty()); - BOOST_CONTRACT_ASSERT(get_allocator() == allocator); + BOOST_CONTRACT_ASSERT(get_allocator() == alloc); }) ; } explicit vector(size_type count) : vect_(count) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->size() == count); + BOOST_CONTRACT_ASSERT(size() == count); BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( - boost::bind(all_of_equal(), begin(), end(), T()) - ).else_(always(true)) + boost::contract::check_if >( + boost::bind(all_of_equal_to(), begin(), end(), T()) + ) ); }) ; } vector(size_type count, T const& value) : vect_(count, value) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(size() == count); BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( - boost::bind( - &boost::algorithm::all_of_equal< - const_iterator, T>, - begin(), end(), boost::cref(value) - ) - ).else_([] { return true; }) + boost::contract::check_if >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) ); }) ; } + vector(size_type count, const T& value, Allocator const& alloc) : + vect_(count, value, alloc) { + boost::contract::guard c = boost::contract::constructor(this) + .postcondition([&] { + BOOST_CONTRACT_ASSERT(size() == count); + BOOST_CONTRACT_ASSERT( + boost::contract::check_if >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) + ); + BOOST_CONTRACT_ASSERT(alloc == get_allocator()); + }) + ; + } + template vector(InputIter first, InputIter last) : vect_(first, last) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(std::distance(first, last) == int(size())); @@ -123,25 +121,25 @@ public: } template - vector(InputIter first, InputIter last, Alloc const& allocator) : - vect_(first, last, allocator) { - auto c = boost::contract::constructor(this) + vector(InputIter first, InputIter last, Allocator const& alloc) : + vect_(first, last, alloc) { + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(std::distance(first, last) == int(size())); - BOOST_CONTRACT_ASSERT(get_allocator() == allocator); + BOOST_CONTRACT_ASSERT(get_allocator() == alloc); }) ; } /* implicit */ vector(vector const& other) : vect_(other.vect_) { - auto c = boost::contract::constructor(this) + boost::contract::guard c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( + boost::contract::check_if >( boost::bind(std::equal_to >(), boost::cref(*this), boost::cref(other)) - ).else_(always(true)) + ) ); }) ; @@ -149,32 +147,33 @@ public: vector& operator=(vector const& other) { boost::optional result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT( - boost::contract::call_if > >( + boost::contract::check_if >( boost::bind(std::equal_to >(), boost::cref(*this), boost::cref(other)) - ).else_([] { return true; }) + ) ); BOOST_CONTRACT_ASSERT( - boost::contract::call_if > >( + boost::contract::check_if >( boost::bind(std::equal_to >(), boost::cref(*result), boost::cref(*this)) - ).else_([] { return true; }) + ) ); }) ; + if(this != &other) vect_ = other.vect_; return *(result = *this); } - virtual ~vector() { auto c = boost::contract::destructor(this); } + virtual ~vector() { + boost::contract::guard c = boost::contract::destructor(this); + } void reserve(size_type count) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count < max_size()); }) @@ -188,7 +187,7 @@ public: size_type capacity() const { size_type result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(result >= size()); }) @@ -199,9 +198,9 @@ public: iterator begin() { iterator result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { - if(this->empty()) BOOST_CONTRACT_ASSERT(result == end()); + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); }) ; @@ -210,9 +209,9 @@ public: const_iterator begin() const { const_iterator result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { - if(this->empty()) BOOST_CONTRACT_ASSERT(result == end()); + if(empty()) BOOST_CONTRACT_ASSERT(result == end()); }) ; @@ -220,18 +219,18 @@ public: } iterator end() { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.end(); } const_iterator end() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.end(); } reverse_iterator rbegin() { iterator result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { if(empty()) BOOST_CONTRACT_ASSERT(result == rend()); }) @@ -242,9 +241,9 @@ public: const_reverse_iterator rbegin() const { const_reverse_iterator result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { - if(this->empty()) BOOST_CONTRACT_ASSERT(result == rend()); + if(empty()) BOOST_CONTRACT_ASSERT(result == rend()); }) ; @@ -252,31 +251,27 @@ public: } reverse_iterator rend() { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.rend(); } const_reverse_iterator rend() const { - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.rend(); } void resize(size_type count, T const& value = T()) { - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(size() == count); if(count > *old_size) { BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( - boost::bind( - &boost::algorithm::all_of_equal< - const_iterator, T>, - begin() + *old_size, - end(), - boost::cref(value) - ) - ).else_([] { return true; }) + boost::contract::check_if >( + boost::bind(all_of_equal_to(), begin() + *old_size, + end(), boost::cref(value)) + ) ); } }) @@ -287,7 +282,7 @@ public: size_type size() const { size_type result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(result <= capacity()); }) @@ -298,7 +293,7 @@ public: size_type max_size() const { size_type result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(result >= capacity()); }) @@ -309,34 +304,34 @@ public: bool empty() const { bool result; - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { - BOOST_CONTRACT_ASSERT(result == (this->size() == 0)); + BOOST_CONTRACT_ASSERT(result == (size() == 0)); }) ; return vect_.empty(); } - Alloc get_allocator() const { - auto c = boost::contract::public_function(this); + Allocator get_allocator() const { + boost::contract::guard c = boost::contract::public_function(this); return vect_.get_allocator(); } reference at(size_type index) { // No precondition because throws out_of_range for invalid index. - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.at(index); } const_reference at(size_type index) const { // No precondition because throws out_of_range for invalid index. - auto c = boost::contract::public_function(this); + boost::contract::guard c = boost::contract::public_function(this); return vect_.at(index); } reference operator[](size_type index) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(index < size()); }) @@ -346,7 +341,7 @@ public: } const_reference operator[](size_type index) const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(index < size()); }) @@ -356,7 +351,7 @@ public: } reference front() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -366,7 +361,7 @@ public: } const_reference front() const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -376,7 +371,7 @@ public: } reference back() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -386,7 +381,7 @@ public: } const_reference back() const { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -396,20 +391,22 @@ public: } void push_back(T const& value) { - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto old_capacity = BOOST_CONTRACT_OLDOF(capacity()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { - BOOST_CONTRACT_ASSERT(this->size() < max_size()); + BOOST_CONTRACT_ASSERT(size() < max_size()); }) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->size() == *old_size + 1); + BOOST_CONTRACT_ASSERT(size() == *old_size + 1); BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( + boost::contract::check_if >( boost::bind(std::equal_to(), boost::cref(back()), boost::cref(value)) - ).else_([] { return true; }) + ) ); }) ; @@ -418,8 +415,9 @@ public: } void pop_back() { - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); }) @@ -433,7 +431,7 @@ public: template void assign(InputIter first, InputIter last) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) // Precondition: [begin(), end()) does not contain [first, last). .postcondition([&] { BOOST_CONTRACT_ASSERT(std::distance(first, last) == @@ -445,19 +443,16 @@ public: } void assign(size_type count, T const& value) { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(count <= max_size()); }) .postcondition([&] { BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( - boost::bind( - &boost::algorithm::all_of_equal< - const_iterator, T>, - begin(), end(), boost::cref(value) - ) - ).else_([] { return true; }) + boost::contract::check_if >( + boost::bind(all_of_equal_to(), begin(), end(), + boost::cref(value)) + ) ); }) ; @@ -467,18 +462,19 @@ public: iterator insert(iterator where, T const& value) { iterator result; - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(size() < max_size()); }) .postcondition([&] { BOOST_CONTRACT_ASSERT(size() == *old_size + 1); BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( + boost::contract::check_if >( boost::bind(std::equal_to(), boost::cref(*result), boost::cref(value)) - ).else_([] { return true; }) + ) // if(capacity() > oldof capacity()) // [begin(), end()) is invalid // else @@ -491,27 +487,32 @@ public: } void insert(iterator where, size_type count, T const& value) { - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto old_capacity = BOOST_CONTRACT_OLDOF(capacity()); - auto old_where = BOOST_CONTRACT_OLDOF(where); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::old_ptr old_where = + BOOST_CONTRACT_OLDOF(where); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { - BOOST_CONTRACT_ASSERT(this->size() + count < max_size()); + BOOST_CONTRACT_ASSERT(size() + count < max_size()); }) .postcondition([&] { - BOOST_CONTRACT_ASSERT(this->size() == *old_size + count); + BOOST_CONTRACT_ASSERT(size() == *old_size + count); BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); if(capacity() == *old_capacity) { BOOST_CONTRACT_ASSERT( - boost::contract::call_if >( - boost::bind(all_of_equal(), + boost::contract::check_if >( + boost::bind(all_of_equal_to(), boost::prior(*old_where), boost::prior(*old_where) + count, boost::cref(value) ) - ).else_(always(true)) + ) ); + // [where, end()) is invalid } + // else [begin(), end()) is invalid }) ; @@ -520,9 +521,11 @@ public: template void insert(iterator where, InputIter first, InputIter last) { - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto old_capacity = BOOST_CONTRACT_OLDOF(capacity()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::old_ptr old_capacity = + BOOST_CONTRACT_OLDOF(capacity()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(size() + std::distance(first, last) < max_size()); @@ -540,14 +543,15 @@ public: iterator erase(iterator where) { iterator result; - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!empty()); BOOST_CONTRACT_ASSERT(where != end()); }) .postcondition([&] { - BOOST_CONTRACT_ASSERT(size() == *old_size + 1); + BOOST_CONTRACT_ASSERT(size() == *old_size - 1); if(empty()) BOOST_CONTRACT_ASSERT(result == end()); // [where, end()) is invalid }) @@ -558,13 +562,14 @@ public: iterator erase(iterator first, iterator last) { iterator result; - auto old_size = BOOST_CONTRACT_OLDOF(size()); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_size = + BOOST_CONTRACT_OLDOF(size()); + boost::contract::guard c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(size() >= std::distance(first, last)); }) .postcondition([&] { - BOOST_CONTRACT_ASSERT(size() == *old_size + + BOOST_CONTRACT_ASSERT(size() == *old_size - std::distance(first, last)); if(empty()) BOOST_CONTRACT_ASSERT(result == end()); // [first, last) is invalid @@ -575,7 +580,7 @@ public: } void clear() { - auto c = boost::contract::public_function(this) + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(empty()); }) @@ -585,23 +590,24 @@ public: } void swap(vector& other) { - auto old_me = BOOST_CONTRACT_OLDOF(*this); - auto old_other = BOOST_CONTRACT_OLDOF(other); - auto c = boost::contract::public_function(this) + boost::contract::old_ptr old_me = BOOST_CONTRACT_OLDOF(*this); + boost::contract::old_ptr old_other = + BOOST_CONTRACT_OLDOF(other); + boost::contract::guard c = boost::contract::public_function(this) .postcondition([&] { BOOST_CONTRACT_ASSERT( - boost::contract::call_if > >( boost::bind(std::equal_to >(), boost::cref(*this), boost::cref(*old_other)) - ).else_([] { return true; }) + ) ); BOOST_CONTRACT_ASSERT( - boost::contract::call_if > >( boost::bind(std::equal_to >(), boost::cref(other), boost::cref(*old_me)) - ).else_([] { return true; }) + ) ); }) ; @@ -614,56 +620,50 @@ public: } private: - std::vector vect_; + std::vector vect_; }; - -struct x {}; - -template -decltype(boost::declval()()) r(F f) { -// std::cout << typeid(t).name() << std::endl; - return "abc"; -} - + int main() { - // Test vector of equality comparable type `char`. + // char type has operator==. vector v(3); - BOOST_TEST_EQ(v.size(), 3); - BOOST_TEST(boost::algorithm::all_of_equal(v, '\0')); + assert(v.size() == 3); + assert(boost::algorithm::all_of_equal(v, '\0')); + vector const& cv = v; + assert(cv == v); vector w(v); - BOOST_TEST(w == v); // Cannot use TEST_EQ here (because it'd print w and v). + assert(w == v); - vector::iterator i = v.begin(); - BOOST_TEST_EQ(*i, '\0'); + typename vector::iterator i = v.begin(); + assert(*i == '\0'); - vector::const_iterator ci = cv.begin(); - BOOST_TEST_EQ(*ci, '\0'); + typename vector::const_iterator ci = cv.begin(); + assert(*ci == '\0'); v.insert(i, 2, 'a'); - BOOST_TEST_EQ(v[0], 'a'); - BOOST_TEST_EQ(v[1], 'a'); + assert(v[0] == 'a'); + assert(v[1] == 'a'); v.push_back('b'); - BOOST_TEST_EQ(v.back(), 'b'); + assert(v.back() == 'b'); - // Test vector of non equality comparable type `x`. + struct x {}; // x type doest not have operator==. vector y(3); - BOOST_TEST_EQ(y.size(), 3); - vector const& cy = y; + assert(y.size() == 3); + vector const& cy = y; vector z(y); - vector::iterator j = y.begin(); - - vector::const_iterator cj = cy.begin(); + typename vector::iterator j = y.begin(); + typename vector::const_iterator cj = cy.begin(); y.insert(j, 2, x()); + y.push_back(x()); - return boost::report_errors(); + return 0; } //] diff --git a/example/n1962/vector_n1962.hpp b/example/n1962/vector_n1962.hpp index 15dfd3d..91ea572 100644 --- a/example/n1962/vector_n1962.hpp +++ b/example/n1962/vector_n1962.hpp @@ -1,23 +1,31 @@ -// Copyright (C) 2008-2012 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) -// Home at http://sourceforge.net/projects/contractpp - //[n1962_vector_n1962 -// Extra newlines, etc. used to align text with this library code. +// Extra spaces, newlines, etc. for visual alignment with this library code. -#include #include -#include -#include +#include +#include #include +#include +#include + + + + + + + + + + + + template< class T, class Allocator = std::allocator > -class vector -{ +class vector { + + invariant { empty() == (size() == 0); std::distance(begin(), end()) == int(size()); @@ -26,473 +34,636 @@ class vector capacity() <= max_size(); } - public: typedef typename std::vector::allocator_type - allocator_type; - public: typedef typename std::vector::pointer pointer; - public: typedef typename std::vector::const_pointer - const_pointer; - public: typedef typename std::vector::reference reference; - public: typedef typename std::vector::const_reference - const_reference; - public: typedef typename std::vector::value_type value_type; - public: typedef typename std::vector::iterator iterator; - public: typedef typename std::vector::const_iterator - const_iterator; - public: typedef typename std::vector::size_type size_type; - public: typedef typename std::vector::difference_type - difference_type; - public: typedef typename std::vector::reverse_iterator +public: + typedef typename std::vector::allocator_type allocator_type; + typedef typename std::vector::pointer pointer; + typedef typename std::vector::const_pointer const_pointer; + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + typedef typename std::vector::value_type value_type; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::size_type size_type; + typedef typename std::vector::difference_type difference_type; + typedef typename std::vector::reverse_iterator reverse_iterator; - public: typedef typename std::vector::const_reverse_iterator + typedef typename std::vector::const_reverse_iterator const_reverse_iterator; - - public: vector ( void ) - postcondition { not empty(); } - : vector_() + vector() + postcondition { + !empty(); + } + : vect_() {} - - - public: explicit vector ( const Allocator& alllocator ) + + + explicit vector(Allocator const& alloc) postcondition { empty(); - allocator == get_allocator(); + get_allocator() == alloc; } - : vector_(allocator) + : vect_(alloc) {} - - public: explicit vector ( size_type count ) + + explicit vector(size_type count) postcondition { - size() == count; - boost::algorithm::all_of_equal(begin(), end(), T()); - // Assertion requirements not supported by [N1962]. + size() == count; + static if(boost::has_equal_to::value) { + boost::algorithm::all_of_equal(begin(), end(), T()); + } } - : vector_(count) + : vect_(count) {} - - public: vector ( size_type count, const T& value ) + + + + vector(size_type count, T const& value) postcondition { size() == count; - boost::algorithm::all_of_equal(begin(), end(), value); - + static if(boost::has_equal_to::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } } - : vector_(count, value) - {} - - - public: vector ( size_type count, const T& value, - const Allocator& allocator ) - postcondition { - size() == count; - boost::algorithm::all_of_equal(begin(), end(), value); - - allocator == get_allocator(); - } - : vector_(count, value, allocator) - {} - - - public: template< class Iterator > - requires std::InputIterator - vector ( Iterator first, Iterator last ) - postcondition { std::distance(first, last) == int(size()); } - : vector_(first, last) - {} - - - public: template< class Iterator > - requires std::InputIterator - vector ( Iterator first, Iterator last, - const Allocator& allocator ) - postcondition { - std::distance(first, last) == int(size()); - allocator == get_allocator(); - } - : vector_(first, last, allocator) - {} - - - public: vector ( const vector& right ) - postcondition { - right == *this; - } - : vector_(right.vector_) - {} - - - public: vector& operator= ( const vector& right ) - postcondition(result) { - - right == *this; - result == *this; - } - { - return vect_ = right.vect_; - } - - - public: virtual ~vector ( void ) + : vect_(count, value) {} - public: void reserve ( size_type count ) - precondition { count < max_size(); } - postcondition { capacity() >= count; } - { - vector_.reserve(count); - } - - - public: size_type capacity ( void ) const - postcondition(result) { result >= size(); } - { - return vector_.capacity(); - } - - - public: iterator begin ( void ) + + + vector(size_type count, T const& value, Allocator const& alloc) postcondition { + size() == count; + static if(boost::has_equal_to::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } + get_allocator() == alloc; + } + : vect_(count, value, alloc) + {} - if(empty()) { - result == end(); + + + + + + template + vector(InputIter first, InputIter last) + postcondition { + std::distance(first, last) == int(size()); + } + : vect_(first, last) + {} + + + + template + vector(InputIter first, InputIter last, Allocator const& alloc) + postcondition { + std::distance(first, last) == int(size()); + get_allocator() == alloc; + } + : vect_(first, last, alloc) + {} + + + + + /* implicit */ vector(vector const& other) + postcondition { + static if(boost::has_equal_to::value) { + *this == other; + } + } + : vect_(other.vect_) + {} + + + + + + vector& operator=(vector const& other) + postcondition(result) { + static if(boost::has_equal_to::value) { + *this == other; + result == *this; } } { - return vector_.begin(); + if(this != &other) vect_ = other.vect_; + return *this; } - public: const_iterator begin ( void ) const - postcondition(result) { - - if(empty()) { result == end(); } + + + + + + + + + + + virtual ~vector() {} + + + + void reserve(size_type count) + precondition { + count < max_size(); } - { - return vector_.begin(); - } - - - public: iterator end ( void ) - { - return vector_.end(); - } - - - public: const_iterator end ( void ) const - { - return vector_.end(); - } - - - public: reverse_iterator rbegin ( void ) - postcondition(result) { - - if(empty()) { result == rend(); } - } - { - return vector_.rbegin(); - } - - - public: const_reverse_iterator rbegin ( void ) const - postcondition(result) { - - if(empty()) { result == rend(); } - } - { - return vector_.rbegin(); - } - - - public: reverse_iterator rend ( void ) - { - return vector_.rend(); - } - - - public: const_reverse_iterator rend ( void ) const - { - return vector_.rend(); - } - - - public: void resize ( size_type count ) postcondition { + capacity() >= count; + } + { + vect_.reserve(count); + } + + + size_type capacity() const + postcondition(result) { + result >= size(); + } + { + return vect_.capacity(); + } + + + + + iterator begin() + postcondition { + if(empty()) result == end(); + } + { + return vect_.begin(); + } + + + + + const_iterator begin() const + postcondition(result) { + if(empty()) result == end(); + } + { + return vect_.begin(); + } + + + + + iterator end() { + return vect_.end(); + } + + + const_iterator end() const { + return vect_.end(); + } + + + reverse_iterator rbegin() + postcondition(result) { + if(empty()) result == rend(); + } + { + return vect_.rbegin(); + } + + + + + const_reverse_iterator rbegin() const + postcondition(result) { + if(empty()) result == rend(); + } + { + return vect_.rbegin(); + } + + + + + reverse_iterator rend() { + return vect_.rend(); + } + + + const_reverse_iterator rend() const { + return vect_.rend(); + } + + + void resize(size_type count, T const& value = T()) + postcondition { size() == count; - if(count > oldof size()) { - boost::algorithm::all_of_equal(begin() + oldof size(), end(), - T()); + static if(boost::has_equal_to::value) { + if(count > oldof size()) { + boost::algorithm::all_of_equal(begin() + oldof size(), + end(), value); + } } } { - vectcor_.resize(count); + vect_.resize(count, value); } - public: void resize ( size_type count, T value ) - postcondition { - size() == count; - count > oldof size() ? - boost::algorithm::all_of_equal(begin() + oldof size(), end(), - value) - : - true - ; + + + + + size_type size() const + postcondition(result) { + result <= capacity(); } { - vector_.resize(count, value); + return vect_.size(); } - public: size_type size ( void ) const - postcondition(result) { result <= capacity(); } - { - return vector_.size(); - } - - - public: size_type max_size ( void ) const - postcondition(result) { result >= capacity(); } - { - return vector_.max_size(); - } - - - public: bool empty ( void ) const + + + size_type max_size() const + postcondition(result) { + result >= capacity(); + } + { + return vect_.max_size(); + } + + + + + bool empty() const postcondition(result) { - result == (size() == 0); } { - return vector_.empty(); + return vect_.empty(); } - public: Alloctor get_allocator ( void ) const - { - return vector_.get_allocator(); + + + Alloctor get_allocator() const { + return vect_.get_allocator(); } - public: reference at ( size_type index ) - precondition { index < size(); } - { - return vectcor_.at(index); + reference at(size_type index) { + // No precondition because throws out_of_range for invalid index. + return vect_.at(index); } - public: const_reference at ( size_type index ) const - precondition { index < size(); } - { - return vector_.at(index); + const_reference at(size_type index) const { + // No precondition because throws out_of_range for invalid index. + return vect_.at(index); } - public: reference operator[] ( size_type index ) - precondition { index < size(); } - { - return vector_[index]; - } - - - public: const_reference operator[] ( size_type index ) const - precondition { index < size(); } - { - return vectcor_[index]; - } - - - public: reference front ( void ) - precondition { not empty(); } - { - return vectcor_.front(); - } - - - public: const_reference front ( void ) const - precondition { bool(!empty()); } - { - return vector_.front(); - } - - - public: reference back ( void ) - precondition { not empty(); } - { - return vector_.back(); - } - - - public: const_reference back ( void ) const - precondition { not empty(); } - { - return vector_.back(); - } - - - public void push_back ( const T& value ) - precondition { size() < max_size() } - postcondition { - - - static if(boost::has_equal_to::value) { back() == value; } - size() == oldof size() + 1; - capacity() >= oldof capacity() + reference operator[](size_type index) + precondition { + index < size(); } { - vector_.push_back(value); + return vect_[index]; } - public: void pop_back ( void ) - precondition { not empty(); } - postcondition { + + const_reference operator[](size_type index) const + precondition { + index < size(); + } + { + return vect_[index]; + } + + + reference front() + precondition { + !empty(); + } + { + return vect_.front(); + } + + + + const_reference front() const + precondition { + !empty(); + } + { + return vect_.front(); + } + + + + reference back() + precondition { + empty(); + } + { + return vect_.back(); + } + + + + const_reference back() const + precondition { + empty(); + } + { + return vect_.back(); + } + + + + void push_back(T const& value) + precondition { + size() < max_size(); + } + postcondition { + size() == oldof size() + 1; + capacity() >= oldof capacity() + static if(boost::has_equal_to::value) { + back() == value; + } + } + { + vect_.push_back(value); + } + + + + + + + + + + + void pop_back() + precondition { + !empty(); + } + postcondition { size() == oldof size() - 1; } { - vector_.pop_back(); + vect_.pop_back(); } - public: template< class Iterator > - requires std::InputIterator - void assign ( Iterator first, Iterator last ) - // precondition: [begin(), end()) does not contain [first, last) - postcondition { std::distance(first, last) == int(size()); } - { - vector_.assign(first, last); - } - - - public: void assign ( size_type count, const T& vallue ) - precondition { count <= max_size(); } + + + + template + void assign(InputIter first, InputIter last) + // Precondition: [begin(), end()) does not contain [first, last). postcondition { - boost::algorithm::all_of_equal(begin(), end(), value); - + std::distance(first, last) == int(size()); } { - vector_.assign(count, value); + vect_.assign(first, last); } - public: iterator insert ( iterator where, const T& value ) - precondition { size() < max_size(); } + + + void assign(size_type count, T const& vallue) + precondition { + count <= max_size(); + } + postcondition { + static if(boost::has_equal_to::value) { + boost::algorithm::all_of_equal(begin(), end(), value); + } + } + { + vect_.assign(count, value); + } + + + + + + + iterator insert(iterator where, T const& value) + precondition { + size() < max_size(); + } postcondition(result) { - - - value == *result; size() == oldof size() + 1; + static if(boost::has_equal_to::value) { + *result == value; + } // if(capacity() > oldof capacity()) // [begin(), end()) is invalid // else // [where, end()) is invalid } { - return vector_.insert(where, value); + return vect_.insert(where, value); } - public: void insert ( iterator where, size_type count, - const T& value ) - precondition { size() + count < max_size(); } + + + + + + + + void insert(iterator where, size_type count, T const& value) + precondition { + size() + count < max_size(); + } postcondition { - - - - size() == oldof size() + count; capacity() >= oldof capacity(); - if(capacity() == oldof capacity()) { - boost::algorithm::all_of_equal(boost::prior(oldof where), - boost::prior(oldof where) + count, value); - + static if(boost::has_equal_to::value) { + if(capacity() == oldof capacity()) { + boost::algorithm::all_of_equal(boost::prior(oldof where), + boost::prior(oldof where) + count, value); + } // [where, end()) is invalid - } // else [begin(), end()) is invalid + } + // else [begin(), end()) is invalid } { - vector_.insert(where, count, value); + vect_.insert(where, count, value); } - public: template< class Iterator > - requires std::InputIterator - void insert ( iterator where, Iterator first, Iterator last ) + + + + + + + + + + + + + template + void insert(iterator where, Iterator first, Iterator last) precondition { - // [first, last) is not contained in [begin(), end()) size() + std::distance(first, last) < max_size(); + // [first, last) is not contained in [begin(), end()) } postcondition { - - size() == oldof size() + std::distance(first, last); capacity() >= oldof capacity(); } { - vector_.insert(where, first, last); + vect_.insert(where, first, last); } - public: iterator erase ( iterator where ) + + + + + + + + iterator erase(iterator where) precondition { - not empty(); + !empty(); where != end(); } postcondition(result) { - - size() == oldod size() - 1; - if(empty()) { result == end(); } + if(empty()) result == end(); // [where, end()) is invalid } { - return vector_.erase(where); + return vect_.erase(where); } - public: iterator erase ( iterator first, iterator last ) - precondition { size() >= std::distance(first, lasst); } + + + + + iterator erase(iterator first, iterator last) + precondition { + size() >= std::distance(first, lasst); + } postcondition(result) { - - size() == oldof size() - std::distance(first, last); - if(empty()) { result == end(); } + if(empty()) result == end(); // [first, last) is invalid } { - return vector_.erase(first, last); + return vect_.erase(first, last); } - public: void clear ( void ) - postcondition( empty() ) - { - vector_.clear(); - } - - - public: void swap ( vector& right ) + + + + + + void clear() postcondition { - - - right == oldof *this; - oldof right == *this; + empty(); } { - vector_.swap(right); + vect_.clear(); } - friend bool operator== ( vector const& left, vector const& right ) + + + void swap(vector& other) + postcondition { + static if(boost::has_equal_to::value) { + *this == oldof other; + other == oldof *this; + } + } { - return left.vector_ == right.vector_; + vect_.swap(other); } - private: std::vector vector_; + + + + + + + + + + + + + + + + friend bool operator==(vector const& left, vector const& right) { + return left.vect_ == right.vect_; + } + +private: + std::vector vect_; }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// End. //] diff --git a/example/stroustrup97/string.cpp b/example/stroustrup97/string.cpp deleted file mode 100644 index d8e720f..0000000 --- a/example/stroustrup97/string.cpp +++ /dev/null @@ -1,126 +0,0 @@ - -//[stroustrup97_string -#include -#include -#include -#include - -// Adapted from an example presented in the book "The C++ Programming Language" -// (Stroustrup, 1997) to illustrate importance of class invariants. Simple -// preconditions were added where it made sense. -// This should be compiled with postconditions checking turned off (define the -// `BOOST_CONTRACT_NO_POSTCONDITIONS` macro) because postconditions are -// deliberately not used here. -// See referenced book for a discussion on the importance of class invariants, -// and on pros and cons of using pre and post conditions. -class string - #define BASES private boost::contract::constructor_precondition - : BASES -{ -public: - typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; - #undef BASES - - // Here contracts throw these exceptions instead of terminating on failure. - struct invariant_error {}; - struct range_error {}; - struct null_error {}; - struct too_large_error {}; - - enum { too_large = 16000 }; // Length limit. - - void invariant() const { - if(!chars_) throw invariant_error(); - if(size_ < 0) throw invariant_error(); - if(size_ > too_large) throw invariant_error(); - if(chars_[size_] != '\0') throw invariant_error(); - } - - /* implicit */ string(char const* chars) : - boost::contract::constructor_precondition([&] { - if(!chars) throw string::null_error(); - if(strlen(chars) > too_large) throw too_large_error(); - }) - { - auto c = boost::contract::constructor(this); // Check invariants. - init(chars); - } - - /* implicit */ string(string const& other) { - auto c = boost::contract::constructor(this); // Check invariants. - init(other.chars_); - } - - ~string() { - auto c = boost::contract::destructor(this); // Check invariants. - delete[] chars_; - } - - char& operator[](int index) { - auto c = boost::contract::public_function(this) - .precondition([&] { - if(index < 0) throw string::range_error(); - if(index >= size_) throw string::range_error(); - }) - ; - - return chars_[index]; - } - - int size() const { - auto c = boost::contract::public_function(this); // Check invariants. - return size_; - } - -private: - void init(char const* chars) { // Non public so does not check invariants. - auto c = boost::contract::function() - .precondition([&] { - if(!chars) throw string::null_error(); - }) - ; - - size_ = strlen(chars); - chars_ = new char[size_ + 1]; - for(int i = 0; i < size_; ++i) chars_[i] = chars[i]; - chars_[size_] = '\0'; - } - - int size_; - char* chars_; -}; - -void throwing_handler(boost::contract::from context) { - if(context == boost::contract::from_destructor) { - // Ignore exception because destructors should never throw. - std::cerr << "destructor contract failed (ignored)" << std::endl; - } else { - throw; // Re-throw active exception throw by the contract. - } -} - -int main() { - boost::contract::set_precondition_failed(&throwing_handler); - boost::contract::set_postcondition_failed(&throwing_handler); - boost::contract::set_invariant_failed(&throwing_handler); - - string s("abc"); - BOOST_TEST_EQ(s[0], 'a'); - - bool pass = false; - try { - std::cout << "1" << std::endl; - s[3]; - std::cout << "2" << std::endl; - } // Out of range. - catch(string::range_error const&) { - std::cout << "3" << std::endl; - pass = true; - } - std::cout << "4" << std::endl; - BOOST_TEST(pass); - - return boost::report_errors(); -} -//] - diff --git a/include/boost/contract/detail/condition/check_base.hpp b/include/boost/contract/detail/condition/check_base.hpp index f016189..a89840a 100644 --- a/include/boost/contract/detail/condition/check_base.hpp +++ b/include/boost/contract/detail/condition/check_base.hpp @@ -28,10 +28,10 @@ public: explicit check_base(boost::contract::from from) : BOOST_CONTRACT_ERROR_missing_guard_declaration(false) , guard_asserted_(false) - , from_(from) #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ !defined(BOOST_CONTRACT_NO_INVARIANTS) + , from_(from) , failed_(false) #endif {} @@ -112,10 +112,10 @@ private: // TODO: Document all BOOST_CONTRACT_ERROR_... and BOOST_STATIC_ASSERT_MSG errors (in an annex...). bool BOOST_CONTRACT_ERROR_missing_guard_declaration; bool guard_asserted_; // Avoid throwing twice from dtors (undef behavior). - boost::contract::from from_; #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ !defined(BOOST_CONTRACT_NO_INVARIANTS) + boost::contract::from from_; bool failed_; #endif #ifndef BOOST_CONTRACT_NO_PRECONDITIONS diff --git a/include/boost/contract/old.hpp b/include/boost/contract/old.hpp index 75175ce..0e07d34 100644 --- a/include/boost/contract/old.hpp +++ b/include/boost/contract/old.hpp @@ -70,39 +70,6 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro #endif // variadics -/* PRIVATE */ - -#ifdef BOOST_CONTRACT_NO_POSTCONDITIONS - #define BOOST_CONTRACT_OLD_POSTCONDITIONS_ 0 -#else - #define BOOST_CONTRACT_OLD_POSTCONDITIONS_ 1 -#endif - -// Used to avoid exposing entire shared_ptr API (e.g., client stealing -// pointer ownership could break this library). -#define BOOST_CONTRACT_OLD_PTR_DEF_(pointer_name, pointed_type) \ - public: \ - typedef pointed_type element_type; \ - \ - pointer_name() {} \ - \ - /* only const access (contracts should not change old values) */ \ - \ - pointed_type const* operator->() const { return ptr_.operator->(); } \ - \ - BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(pointer_name, \ - !!ptr_) \ - \ - private: \ - BOOST_PP_EXPR_IIF(BOOST_CONTRACT_OLD_POSTCONDITIONS_, \ - explicit pointer_name(boost::shared_ptr ptr) : \ - ptr_(ptr) {} \ - ) \ - \ - boost::shared_ptr ptr_; \ - \ - friend class convertible_old; - /* CODE */ // Specialization because `unconvertible_old` incomplete type when trait used. @@ -118,40 +85,82 @@ namespace boost { namespace boost { namespace contract { template -class noncopyable_old_ptr; +class old_ptr_noncopyable; template class old_ptr { /* copyable (as *) */ - BOOST_CONTRACT_OLD_PTR_DEF_(old_ptr, T) - public: + typedef T element_type; + + old_ptr() {} + + /* only const access (contracts should not change old values) */ + T const& operator*() const { - // Compiler error if old_ptr::operator* and non-copyable T. BOOST_STATIC_ASSERT_MSG( boost::is_copy_constructible::value, -"old_ptr requires T copy constructor, otherwise use noncopyable_old_ptr" +"old_ptr requires T copy constructor, otherwise use old_ptr_noncopyable" ); BOOST_CONTRACT_DETAIL_DEBUG(ptr_); return *ptr_; } - friend class noncopyable_old_ptr; + T const* operator->() const { + BOOST_STATIC_ASSERT_MSG( + boost::is_copy_constructible::value, +"old_ptr requires T copy constructor, otherwise use old_ptr_noncopyable" + ); + return ptr_.operator->(); + } + + BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr, !!ptr_) + +private: + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + explicit old_ptr(boost::shared_ptr ptr) : + ptr_(ptr) {} + #endif + + boost::shared_ptr ptr_; + + friend class convertible_old; + friend class old_ptr_noncopyable; }; +// Similar to above, but does not statically assert copy constructible. template -class noncopyable_old_ptr { /* copyable (as *) */ - BOOST_CONTRACT_OLD_PTR_DEF_(noncopyable_old_ptr, T) - +class old_ptr_noncopyable { /* copyable (as *) */ public: + typedef T element_type; + + old_ptr_noncopyable() {} + // Required to assign to OLDOF (as OLDOF returns old_ptr for auto decl). - /* implicit */ noncopyable_old_ptr(old_ptr const& other) : + /* implicit */ old_ptr_noncopyable(old_ptr const& other) : ptr_(other.ptr_) {} + /* only const access (contracts should not change old values) */ + T const& operator*() const { - // No static assert is_copy_constructible so T can be non-copyable here. BOOST_CONTRACT_DETAIL_DEBUG(ptr_); return *ptr_; } + + T const* operator->() const { + return ptr_.operator->(); + } + + BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_noncopyable, !!ptr_) + +private: + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + explicit old_ptr_noncopyable(boost::shared_ptr ptr) : + ptr_(ptr) {} + #endif + + boost::shared_ptr ptr_; + + friend class convertible_old; }; class unconvertible_old { // Copyable (as *). @@ -188,10 +197,10 @@ private: class convertible_old { // Copyable (as *). public: - // Implicitly called by ctor init `noncopyable_old_ptr old_x = ...`. + // Implicitly called by ctor init `old_ptr_noncopyable old_x = ...`. template - /* implicit */ operator noncopyable_old_ptr() { - return ptr >(); + /* implicit */ operator old_ptr_noncopyable() { + return ptr >(); } // Implicitly called by ctor init `old_ptr old_x = ...`. diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 04d7235..46f260e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -211,16 +211,6 @@ test-suite old [ subdir-compile-fail old : no_equal_error ] ; -test-suite union -: - [ subdir-run-with-no union : contracts ] -; - -test-suite move -: - [ subdir-run-with-no move : contracts ] -; - test-suite disable : [ subdir-run-with-no disable : prog ] diff --git a/test/invariant/decl.hpp b/test/invariant/decl.hpp index d74cd16..56d9cb1 100644 --- a/test/invariant/decl.hpp +++ b/test/invariant/decl.hpp @@ -481,23 +481,17 @@ int main() { out.str(""); aa.f('a'); - ok.str(""); ok // Mutable checks static, cv, and const-only inv. + ok.str(""); ok // Mutable checks static and const (but not cv) inv. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "b::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "b::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "b::const_inv" << std::endl #endif #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "a::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "a::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "a::const_inv" << std::endl #endif @@ -515,18 +509,12 @@ int main() { #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "b::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "b::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "b::const_inv" << std::endl #endif #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "a::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "a::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "a::const_inv" << std::endl #endif @@ -782,14 +770,11 @@ int main() { out.str(""); bb.f('b'); - ok.str(""); ok // Mutable checks static, cv, and const-only inv. + ok.str(""); ok // Mutable checks static and const (but not cv) inv. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "b::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "b::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "b::const_inv" << std::endl #endif @@ -805,9 +790,6 @@ int main() { #ifdef BOOST_CONTRACT_TEST_STATIC_INV << "b::static_inv" << std::endl #endif - #ifdef BOOST_CONTRACT_TEST_CV_INV - << "b::cv_inv" << std::endl - #endif #ifdef BOOST_CONTRACT_TEST_CONST_INV << "b::const_inv" << std::endl #endif diff --git a/test/move/contracts.cpp b/test/move/contracts.cpp deleted file mode 100644 index 34a2c7c..0000000 --- a/test/move/contracts.cpp +++ /dev/null @@ -1,165 +0,0 @@ - -// Test contracts for move operations. - -#include -#include -#include -#include -#include -#include -#include -#include - -struct v : boost::contract::constructor_precondition { - void invariant() const { - if(!moved()) { - BOOST_CONTRACT_ASSERT(i_ < w_.size()); - } - } - - v(std::vector const& w, unsigned i) : - boost::contract::constructor_precondition([&] { - BOOST_CONTRACT_ASSERT(i <= w.size()); - }), - w_(w), i_(i), moved_(false) - { - boost::contract::guard c = boost::contract::constructor(this) - .postcondition([&] { BOOST_CONTRACT_ASSERT(!moved()); }) - ; - } - - ~v() { - // Moved-from can be destroyed (so no pre !moved here). - boost::contract::guard c = boost::contract::destructor(this); - } - - v(v const& o) : - boost::contract::constructor_precondition( - [&] { BOOST_CONTRACT_ASSERT(!o.moved()); } - ) - { - boost::contract::guard c = boost::contract::constructor(this) - .postcondition([&] { BOOST_CONTRACT_ASSERT(!moved()); }) - ; - copy(o); - } - - v& operator=(v const& o) { - // Moved-from can be (copy) assigned (so no pre !moved here). - boost::contract::guard c = boost::contract::public_function(this) - .precondition([&] { BOOST_CONTRACT_ASSERT(!o.moved()); }) - .postcondition([&] { BOOST_CONTRACT_ASSERT(!moved()); }) - ; - copy(o); - return *this; - } - - v(v&& o) : - boost::contract::constructor_precondition( - [&] { BOOST_CONTRACT_ASSERT(!o.moved()); } - ) - { - boost::contract::guard c = boost::contract::constructor(this) - .postcondition([&] { - BOOST_CONTRACT_ASSERT(!moved()); - BOOST_CONTRACT_ASSERT(o.moved()); - }) - ; - move(std::forward(o)); - } - - v& operator=(v&& o) { - // Moved-from can be (move) assigned (so no pre !moved here). - boost::contract::guard c = boost::contract::public_function(this) - .precondition([&] { BOOST_CONTRACT_ASSERT(!o.moved()); }) - .postcondition([&] { - BOOST_CONTRACT_ASSERT(!moved()); - BOOST_CONTRACT_ASSERT(o.moved()); - }) - ; - move(std::forward(o)); - return *this; - } - - char at() const { - boost::contract::guard c = boost::contract::public_function(this) - .precondition([&] { BOOST_CONTRACT_ASSERT(!moved()); }) - ; - return w_.at(i_); - } - - bool moved() const { - boost::contract::guard c = boost::contract::public_function(this); - return moved_; - } - -private: - void copy(v const& o) { - w_ = o.w_; - i_ = o.i_; - moved_ = false; - } - - void move(v&& o) { - w_ = std::move(o.w_); - i_ = std::move(o.i_); - moved_ = false; - o.moved_ = true; // Mark moved-from object. - } - - std::vector w_; - unsigned i_; - bool moved_; -}; - -int main() { - struct err {}; - boost::contract::set_precondition_failure( - [] (boost::contract::from) { throw err(); }); - - { - v x = {{'a', 'b', 'c', 'd'}, 2}; - BOOST_TEST_EQ(x.at(), 'c'); - - v y1 = x; // Test copy constructor. - BOOST_TEST_EQ(y1.at(), 'c'); - BOOST_TEST_EQ(x.at(), 'c'); - - v y2 = {{'a'}, 0}; - y2 = x; // Test copy assignment. - BOOST_TEST_EQ(y2.at(), 'c'); - BOOST_TEST_EQ(x.at(), 'c'); - - v z1 = std::move(x); // Test move constructor. - BOOST_TEST_EQ(z1.at(), 'c'); - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - try { x.at(); BOOST_TEST(false); } - catch(err const&) {} // Test !moved() pre failed. - catch(...) { BOOST_TEST(false); } - #endif - - x = y1; // Test moved-from can be copy assigned. - BOOST_TEST_EQ(x.at(), 'c'); - BOOST_TEST_EQ(y1.at(), 'c'); - - v z2 = {{'a'}, 0}; - z2 = std::move(x); // Test move assignment. - BOOST_TEST_EQ(z2.at(), 'c'); - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - try { x.at(); BOOST_TEST(false); } - catch(err const&) {} // Test !moved() pre failed. - catch(...) { BOOST_TEST(false); } - #endif - - x = std::move(y2); // Test moved-from can be move assigned. - BOOST_TEST_EQ(x.at(), 'c'); - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - try { y2.at(); BOOST_TEST(false); } - catch(err const&) {} // Test !moved() pre failed. - catch(...) { BOOST_TEST(false); } - #endif - } // Test moved-from (y2) can be destroyed. - - return boost::report_errors(); -} - diff --git a/test/old/noncopyable.cpp b/test/old/noncopyable.cpp index d5e44de..92b520f 100644 --- a/test/old/noncopyable.cpp +++ b/test/old/noncopyable.cpp @@ -16,7 +16,8 @@ unsigned old_checks; template struct b { virtual void next(T& x, boost::contract::virtual_* v = 0) { - boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF(v, x); + boost::contract::old_ptr_noncopyable old_x = + BOOST_CONTRACT_OLDOF(v, x); boost::contract::guard c = boost::contract::public_function(v, this) .postcondition([&] { if(old_x) { @@ -39,7 +40,8 @@ struct a #undef BASES virtual void next(T& x, boost::contract::virtual_* v = 0) /* override */ { - boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF(v, x); + boost::contract::old_ptr_noncopyable old_x = + BOOST_CONTRACT_OLDOF(v, x); boost::contract::guard c = boost::contract::public_function< override_next>(v, &a::next, this, x) .postcondition([&] { @@ -56,7 +58,7 @@ struct a template void next(T& x) { - boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF(x); + boost::contract::old_ptr_noncopyable old_x = BOOST_CONTRACT_OLDOF(x); boost::contract::guard c = boost::contract::function() .postcondition([&] { if(old_x) { diff --git a/test/old/noncopyable_error.cpp b/test/old/noncopyable_error.cpp index db364bc..ede2e67 100644 --- a/test/old/noncopyable_error.cpp +++ b/test/old/noncopyable_error.cpp @@ -6,13 +6,9 @@ #include #include #include -#include -#include template void next(T& x) { - BOOST_STATIC_ASSERT_MSG(boost::is_copy_constructible::value, - "old-value type must be copy constructible"); // Forces error. boost::contract::old_ptr old_x = BOOST_CONTRACT_OLDOF(x); boost::contract::guard c = boost::contract::function() .postcondition([&] { diff --git a/test/union/contracts.cpp b/test/union/contracts.cpp deleted file mode 100644 index 6da943d..0000000 --- a/test/union/contracts.cpp +++ /dev/null @@ -1,211 +0,0 @@ - -// Test contracts for unions. - -#include "../detail/oteststream.hpp" -#include -#include -#include -#include -#include -#include -#include - -boost::contract::test::detail::oteststream out; - -union u { - int i; - double d; - - static void static_invariant() { out << "u::static_inv" << std::endl; } - void invariant() const { out << "u::inv" << std::endl; } - - u() { - boost::contract::constructor_precondition pre( - [] { out << "u::ctor::pre" << std::endl; } - ); - boost::contract::guard c = boost::contract::constructor(this) - .old([] { out << "u::ctor::old" << std::endl; }) - .postcondition([] { out << "u::ctor::post" << std::endl; }) - ; - out << "u::ctor::body" << std::endl; - } - - ~u() { - boost::contract::guard c = boost::contract::destructor(this) - .old([] { out << "u::dtor::old" << std::endl; }) - .postcondition([] { out << "u::dtor::post" << std::endl; }) - ; - out << "u::dtor::body" << std::endl; - } - - void f() { - boost::contract::guard c = boost::contract::public_function(this) - .precondition([] { out << "u::f::pre" << std::endl; }) - .old([] { out << "u::f::old" << std::endl; }) - .postcondition([] { out << "u::f::post" << std::endl; }) - ; - out << "u::f::body" << std::endl; - } - - static void s() { - boost::contract::guard c = boost::contract::public_function() - .precondition([] { out << "u::s::pre" << std::endl; }) - .old([] { out << "u::s::old" << std::endl; }) - .postcondition([] { out << "u::s::post" << std::endl; }) - ; - out << "u::s::body" << std::endl; - } - -protected: - void g() { - boost::contract::guard c = boost::contract::function() - .precondition([] { out << "u::g::pre" << std::endl; }) - .old([] { out << "u::g::old" << std::endl; }) - .postcondition([] { out << "u::g::post" << std::endl; }) - ; - out << "u::g::body" << std::endl; - } - - friend void call_g(u& me) { me.g(); } - -private: - void h() { - boost::contract::guard c = boost::contract::function() - .precondition([] { out << "u::h::pre" << std::endl; }) - .old([] { out << "u::h::old" << std::endl; }) - .postcondition([] { out << "u::h::post" << std::endl; }) - ; - out << "u::h::body" << std::endl; - } - - friend void call_h(u& me) { me.h(); } -}; - -int main() { - std::ostringstream ok; - - { - out.str(""); - u uu; - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - << "u::ctor::pre" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS - << "u::static_inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::ctor::old" << std::endl - #endif - << "u::ctor::body" << std::endl - #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS - << "u::static_inv" << std::endl - << "u::inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::ctor::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - out.str(""); - uu.f(); - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS - << "u::static_inv" << std::endl - << "u::inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - << "u::f::pre" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::f::old" << std::endl - #endif - << "u::f::body" << std::endl - #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS - << "u::static_inv" << std::endl - << "u::inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::f::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - out.str(""); - uu.s(); - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS - << "u::static_inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - << "u::s::pre" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::s::old" << std::endl - #endif - << "u::s::body" << std::endl - #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS - << "u::static_inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::s::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - out.str(""); - call_g(uu); - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - << "u::g::pre" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::g::old" << std::endl - #endif - << "u::g::body" << std::endl - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::g::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - out.str(""); - call_h(uu); - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - << "u::h::pre" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::h::old" << std::endl - #endif - << "u::h::body" << std::endl - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::h::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - out.str(""); - } // Call destructor. - ok.str(""); ok - #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS - << "u::static_inv" << std::endl - << "u::inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::dtor::old" << std::endl - #endif - << "u::dtor::body" << std::endl - #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS - << "u::static_inv" << std::endl - #endif - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - << "u::dtor::post" << std::endl - #endif - ; - BOOST_TEST(out.eq(ok.str())); - - return boost::report_errors(); -} -