separate_body.hpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #ifndef SEPARATE_BODY_HPP_
  2. #define SEPARATE_BODY_HPP_
  3. // Copyright (C) 2008-2018 Lorenzo Caminiti
  4. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  5. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  6. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  7. #include <boost/contract.hpp>
  8. //[separate_body_hpp
  9. class iarray :
  10. private boost::contract::constructor_precondition<iarray> {
  11. public:
  12. void invariant() const {
  13. BOOST_CONTRACT_ASSERT(size() <= capacity());
  14. }
  15. explicit iarray(unsigned max, unsigned count = 0) :
  16. boost::contract::constructor_precondition<iarray>([&] {
  17. BOOST_CONTRACT_ASSERT(count <= max);
  18. }),
  19. // Still, member initializations must be here.
  20. values_(new int[max]),
  21. capacity_(max)
  22. {
  23. boost::contract::check c = boost::contract::constructor(this)
  24. .postcondition([&] {
  25. BOOST_CONTRACT_ASSERT(capacity() == max);
  26. BOOST_CONTRACT_ASSERT(size() == count);
  27. })
  28. ;
  29. constructor_body(max, count); // Separate constructor body impl.
  30. }
  31. virtual ~iarray() {
  32. boost::contract::check c = boost::contract::destructor(this); // Inv.
  33. destructor_body(); // Separate destructor body implementation.
  34. }
  35. virtual void push_back(int value, boost::contract::virtual_* v = 0) {
  36. boost::contract::old_ptr<unsigned> old_size =
  37. BOOST_CONTRACT_OLDOF(v, size());
  38. boost::contract::check c = boost::contract::public_function(v, this)
  39. .precondition([&] {
  40. BOOST_CONTRACT_ASSERT(size() < capacity());
  41. })
  42. .postcondition([&] {
  43. BOOST_CONTRACT_ASSERT(size() == *old_size + 1);
  44. })
  45. ;
  46. push_back_body(value); // Separate member function body implementation.
  47. }
  48. private:
  49. // Contracts in class declaration (above), but body implementations are not.
  50. void constructor_body(unsigned max, unsigned count);
  51. void destructor_body();
  52. void push_back_body(int value);
  53. /* ... */
  54. //]
  55. public:
  56. unsigned capacity() const {
  57. // Check invariants.
  58. boost::contract::check c = boost::contract::public_function(this);
  59. return capacity_body();
  60. }
  61. unsigned size() const {
  62. // Check invariants.
  63. boost::contract::check c = boost::contract::public_function(this);
  64. return size_body();
  65. }
  66. private:
  67. unsigned size_body() const;
  68. unsigned capacity_body() const;
  69. int* values_;
  70. unsigned capacity_;
  71. unsigned size_;
  72. };
  73. #endif // #include guard