ifdef_macro.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. #include <vector>
  6. #include <limits>
  7. #include <cassert>
  8. //[ifdef_macro_function
  9. // Use macro interface to completely disable contract code compilation.
  10. #include <boost/contract_macro.hpp>
  11. int inc(int& x) {
  12. int result;
  13. BOOST_CONTRACT_OLD_PTR(int)(old_x, x);
  14. BOOST_CONTRACT_FUNCTION()
  15. BOOST_CONTRACT_PRECONDITION([&] {
  16. BOOST_CONTRACT_ASSERT(x < std::numeric_limits<int>::max());
  17. })
  18. BOOST_CONTRACT_POSTCONDITION([&] {
  19. BOOST_CONTRACT_ASSERT(x == *old_x + 1);
  20. BOOST_CONTRACT_ASSERT(result == *old_x);
  21. })
  22. ;
  23. return result = x++;
  24. }
  25. //]
  26. template<typename T>
  27. class pushable {
  28. friend class boost::contract::access; // Left in code (almost no overhead).
  29. BOOST_CONTRACT_INVARIANT({
  30. BOOST_CONTRACT_ASSERT(capacity() <= max_size());
  31. })
  32. public:
  33. virtual void push_back(
  34. T const& x,
  35. boost::contract::virtual_* v = 0 // Left in code (almost no overhead).
  36. ) = 0;
  37. protected:
  38. virtual unsigned capacity() const = 0;
  39. virtual unsigned max_size() const = 0;
  40. };
  41. template<typename T>
  42. void pushable<T>::push_back(T const& x, boost::contract::virtual_* v) {
  43. BOOST_CONTRACT_OLD_PTR(unsigned)(v, old_capacity, capacity());
  44. BOOST_CONTRACT_PUBLIC_FUNCTION(v, this)
  45. BOOST_CONTRACT_PRECONDITION([&] {
  46. BOOST_CONTRACT_ASSERT(capacity() < max_size());
  47. })
  48. BOOST_CONTRACT_POSTCONDITION([&] {
  49. BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity);
  50. })
  51. ;
  52. assert(false); // Shall never execute this body.
  53. }
  54. //[ifdef_macro_class
  55. class integers
  56. #define BASES public pushable<int>
  57. :
  58. // Left in code (almost no overhead).
  59. private boost::contract::constructor_precondition<integers>,
  60. BASES
  61. {
  62. // Followings left in code (almost no overhead).
  63. friend class boost::contract::access;
  64. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  65. #undef BASES
  66. BOOST_CONTRACT_INVARIANT({
  67. BOOST_CONTRACT_ASSERT(size() <= capacity());
  68. })
  69. public:
  70. integers(int from, int to) :
  71. BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION(integers)([&] {
  72. BOOST_CONTRACT_ASSERT(from <= to);
  73. }),
  74. vect_(to - from + 1)
  75. {
  76. BOOST_CONTRACT_CONSTRUCTOR(this)
  77. BOOST_CONTRACT_POSTCONDITION([&] {
  78. BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1));
  79. })
  80. ;
  81. for(int x = from; x <= to; ++x) vect_.at(x - from) = x;
  82. }
  83. virtual ~integers() {
  84. BOOST_CONTRACT_DESTRUCTOR(this); // Check invariants.
  85. }
  86. virtual void push_back(
  87. int const& x,
  88. boost::contract::virtual_* v = 0 // Left in code (almost no overhead).
  89. ) /* override */ {
  90. BOOST_CONTRACT_OLD_PTR(unsigned)(old_size);
  91. BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(override_push_back)(
  92. v, &integers::push_back, this, x)
  93. BOOST_CONTRACT_PRECONDITION([&] {
  94. BOOST_CONTRACT_ASSERT(size() < max_size());
  95. })
  96. BOOST_CONTRACT_OLD([&] {
  97. old_size = BOOST_CONTRACT_OLDOF(v, size());
  98. })
  99. BOOST_CONTRACT_POSTCONDITION([&] {
  100. BOOST_CONTRACT_ASSERT(size() == *old_size + 1);
  101. })
  102. BOOST_CONTRACT_EXCEPT([&] {
  103. BOOST_CONTRACT_ASSERT(size() == *old_size);
  104. })
  105. ;
  106. vect_.push_back(x);
  107. }
  108. private:
  109. BOOST_CONTRACT_OVERRIDE(push_back) // Left in code (almost no overhead).
  110. /* ... */
  111. //]
  112. public: // Could program contracts for these too...
  113. unsigned size() const { return vect_.size(); }
  114. unsigned max_size() const { return vect_.max_size(); }
  115. unsigned capacity() const { return vect_.capacity(); }
  116. private:
  117. std::vector<int> vect_;
  118. };
  119. int main() {
  120. integers i(1, 10);
  121. int x = 123;
  122. i.push_back(inc(x));
  123. assert(x == 124);
  124. assert(i.size() == 11);
  125. return 0;
  126. }