vstack.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright (C) 2008-2018 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  3. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  4. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  5. //[cline90_vstack
  6. #include "vector.hpp"
  7. #include <boost/contract.hpp>
  8. #include <boost/optional.hpp>
  9. #include <cassert>
  10. // NOTE: Incomplete contract assertions, addressing only `empty` and `full`.
  11. template<typename T>
  12. class abstract_stack {
  13. public:
  14. abstract_stack() {
  15. boost::contract::check c = boost::contract::constructor(this)
  16. .postcondition([&] {
  17. // AXIOM as empty() cannot actually be checked here to avoid
  18. // calling pure virtual function length() during construction).
  19. BOOST_CONTRACT_ASSERT_AXIOM(empty());
  20. })
  21. ;
  22. }
  23. virtual ~abstract_stack() {
  24. boost::contract::check c = boost::contract::destructor(this);
  25. }
  26. bool full() const {
  27. bool result;
  28. boost::contract::check c = boost::contract::public_function(this)
  29. .postcondition([&] {
  30. BOOST_CONTRACT_ASSERT(result == (length() == capacity()));
  31. })
  32. ;
  33. return result = (length() == capacity());
  34. }
  35. bool empty() const {
  36. bool result;
  37. boost::contract::check c = boost::contract::public_function(this)
  38. .postcondition([&] {
  39. BOOST_CONTRACT_ASSERT(result = (length() == 0));
  40. })
  41. ;
  42. return result = (length() == 0);
  43. }
  44. virtual int length(boost::contract::virtual_* v = 0) const = 0;
  45. virtual int capacity(boost::contract::virtual_* v = 0) const = 0;
  46. virtual T const& item(boost::contract::virtual_* v = 0) const = 0;
  47. virtual void push(T const& value, boost::contract::virtual_* v = 0) = 0;
  48. virtual T const& pop(boost::contract::virtual_* v = 0) = 0;
  49. virtual void clear(boost::contract::virtual_* v = 0) = 0;
  50. };
  51. template<typename T>
  52. int abstract_stack<T>::length(boost::contract::virtual_* v) const {
  53. int result;
  54. boost::contract::check c = boost::contract::public_function(v, result, this)
  55. .postcondition([&] (int const& result) {
  56. BOOST_CONTRACT_ASSERT(result >= 0);
  57. })
  58. ;
  59. assert(false);
  60. return result;
  61. }
  62. template<typename T>
  63. int abstract_stack<T>::capacity(boost::contract::virtual_* v) const {
  64. int result;
  65. boost::contract::check c = boost::contract::public_function(v, result, this)
  66. .postcondition([&] (int const& result) {
  67. BOOST_CONTRACT_ASSERT(result >= 0);
  68. })
  69. ;
  70. assert(false);
  71. return result;
  72. }
  73. template<typename T>
  74. T const& abstract_stack<T>::item(boost::contract::virtual_* v) const {
  75. boost::optional<T const&> result;
  76. boost::contract::check c = boost::contract::public_function(v, result, this)
  77. .precondition([&] {
  78. BOOST_CONTRACT_ASSERT(!empty());
  79. })
  80. ;
  81. assert(false);
  82. return *result;
  83. }
  84. template<typename T>
  85. void abstract_stack<T>::push(T const& value, boost::contract::virtual_* v) {
  86. boost::contract::check c = boost::contract::public_function(v, this)
  87. .precondition([&] {
  88. BOOST_CONTRACT_ASSERT(!full());
  89. })
  90. .postcondition([&] {
  91. BOOST_CONTRACT_ASSERT(!empty());
  92. })
  93. ;
  94. assert(false);
  95. }
  96. template<typename T>
  97. T const& abstract_stack<T>::pop(boost::contract::virtual_* v) {
  98. boost::optional<T const&> result;
  99. boost::contract::old_ptr<T> old_item = BOOST_CONTRACT_OLDOF(v, item());
  100. boost::contract::check c = boost::contract::public_function(v, result, this)
  101. .precondition([&] {
  102. BOOST_CONTRACT_ASSERT(!empty());
  103. })
  104. .postcondition([&] (boost::optional<T const&> const& result) {
  105. BOOST_CONTRACT_ASSERT(!full());
  106. BOOST_CONTRACT_ASSERT(*result == *old_item);
  107. })
  108. ;
  109. assert(false);
  110. return *result;
  111. }
  112. template<typename T>
  113. void abstract_stack<T>::clear(boost::contract::virtual_* v) {
  114. boost::contract::check c = boost::contract::public_function(v, this)
  115. .postcondition([&] {
  116. BOOST_CONTRACT_ASSERT(empty());
  117. })
  118. ;
  119. assert(false);
  120. }
  121. template<typename T>
  122. class vstack
  123. #define BASES private boost::contract::constructor_precondition< \
  124. vstack<T> >, public abstract_stack<T>
  125. : BASES
  126. {
  127. friend class boost::contract::access;
  128. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  129. #undef BASES
  130. void invariant() const {
  131. BOOST_CONTRACT_ASSERT(length() >= 0);
  132. BOOST_CONTRACT_ASSERT(length() < capacity());
  133. }
  134. BOOST_CONTRACT_OVERRIDES(length, capacity, item, push, pop, clear)
  135. public:
  136. explicit vstack(int count = 10) :
  137. boost::contract::constructor_precondition<vstack>([&] {
  138. BOOST_CONTRACT_ASSERT(count >= 0);
  139. }),
  140. vect_(count), // OK, executed after precondition so count >= 0.
  141. len_(0)
  142. {
  143. boost::contract::check c = boost::contract::constructor(this)
  144. .postcondition([&] {
  145. BOOST_CONTRACT_ASSERT(length() == 0);
  146. BOOST_CONTRACT_ASSERT(capacity() == count);
  147. })
  148. ;
  149. }
  150. virtual ~vstack() {
  151. boost::contract::check c = boost::contract::destructor(this);
  152. }
  153. // Inherited from abstract_stack.
  154. virtual int length(boost::contract::virtual_* v = 0) const /* override */ {
  155. int result;
  156. boost::contract::check c = boost::contract::public_function<
  157. override_length>(v, result, &vstack::length, this);
  158. return result = len_;
  159. }
  160. virtual int capacity(boost::contract::virtual_* v = 0)
  161. const /* override */ {
  162. int result;
  163. boost::contract::check c = boost::contract::public_function<
  164. override_capacity>(v, result, &vstack::capacity, this);
  165. return result = vect_.size();
  166. }
  167. virtual T const& item(boost::contract::virtual_* v = 0)
  168. const /* override */ {
  169. boost::optional<T const&> result;
  170. boost::contract::check c = boost::contract::public_function<
  171. override_item>(v, result, &vstack::item, this);
  172. return *(result = vect_[len_ - 1]);
  173. }
  174. virtual void push(T const& value, boost::contract::virtual_* v = 0)
  175. /* override */ {
  176. boost::contract::check c = boost::contract::public_function<
  177. override_push>(v, &vstack::push, this, value);
  178. vect_[len_++] = value;
  179. }
  180. virtual T const& pop(boost::contract::virtual_* v = 0) /* override */ {
  181. boost::optional<T const&> result;
  182. boost::contract::check c = boost::contract::public_function<
  183. override_pop>(v, result, &vstack::pop, this);
  184. return *(result = vect_[--len_]);
  185. }
  186. virtual void clear(boost::contract::virtual_* v = 0) /* override */ {
  187. boost::contract::check c = boost::contract::public_function<
  188. override_clear>(v, &vstack::clear, this);
  189. len_ = 0;
  190. }
  191. private:
  192. vector<T> vect_;
  193. int len_;
  194. };
  195. int main() {
  196. vstack<int> s(3);
  197. assert(s.capacity() == 3);
  198. s.push(123);
  199. assert(s.length() == 1);
  200. assert(s.pop() == 123);
  201. return 0;
  202. }
  203. //]