assertion_level.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 <boost/contract.hpp>
  6. #include <vector>
  7. #include <algorithm>
  8. #include <iostream>
  9. #include <cassert>
  10. //[assertion_level_no_impl
  11. // If valid iterator range (cannot implement in C++ but OK to use in AXIOM).
  12. template<typename Iter>
  13. bool valid(Iter first, Iter last); // Only declared, not actually defined.
  14. //]
  15. //[assertion_level_class_begin
  16. template<typename T>
  17. class vector {
  18. //]
  19. public:
  20. typedef typename std::vector<T>::iterator iterator;
  21. // Could program class invariants and contracts for the following.
  22. iterator begin() { return vect_.begin(); }
  23. iterator end() { return vect_.end(); }
  24. unsigned capacity() const { return vect_.capacity(); }
  25. bool operator==(vector const& other) { return vect_ == other.vect_; }
  26. //[assertion_level_axiom
  27. public:
  28. iterator insert(iterator where, T const& value) {
  29. iterator result;
  30. boost::contract::old_ptr<unsigned> old_capacity =
  31. BOOST_CONTRACT_OLDOF(capacity());
  32. boost::contract::check c = boost::contract::public_function(this)
  33. .postcondition([&] {
  34. BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity);
  35. if(capacity() > *old_capacity) {
  36. BOOST_CONTRACT_ASSERT_AXIOM(!valid(begin(), end()));
  37. } else {
  38. BOOST_CONTRACT_ASSERT_AXIOM(!valid(where, end()));
  39. }
  40. })
  41. ;
  42. return result = vect_.insert(where, value);
  43. }
  44. //]
  45. //[assertion_level_audit_old
  46. public:
  47. void swap(vector& other) {
  48. boost::contract::old_ptr<vector> old_me, old_other;
  49. #ifdef BOOST_CONTRACT_AUDITS
  50. old_me = BOOST_CONTRACT_OLDOF(*this);
  51. old_other = BOOST_CONTRACT_OLDOF(other);
  52. #endif // Else, skip old value copies...
  53. boost::contract::check c = boost::contract::public_function(this)
  54. .postcondition([&] {
  55. // ...and also skip related assertions.
  56. BOOST_CONTRACT_ASSERT_AUDIT(*this == *old_other);
  57. BOOST_CONTRACT_ASSERT_AUDIT(other == *old_me);
  58. })
  59. ;
  60. vect_.swap(other.vect_);
  61. }
  62. //]
  63. //[assertion_level_class_end
  64. /* ... */
  65. private:
  66. std::vector<T> vect_;
  67. };
  68. //]
  69. //[assertion_level_audit
  70. template<typename RandomIter, typename T>
  71. RandomIter random_binary_search(RandomIter first, RandomIter last,
  72. T const& value) {
  73. RandomIter result;
  74. boost::contract::check c = boost::contract::function()
  75. .precondition([&] {
  76. BOOST_CONTRACT_ASSERT(first <= last); // Default, not expensive.
  77. // Expensive O(n) assertion (use AXIOM if prohibitive instead).
  78. BOOST_CONTRACT_ASSERT_AUDIT(std::is_sorted(first, last));
  79. })
  80. .postcondition([&] {
  81. if(result != last) BOOST_CONTRACT_ASSERT(*result == value);
  82. })
  83. ;
  84. /* ... */
  85. //]
  86. RandomIter begin = first, end = last;
  87. while(begin < end) {
  88. RandomIter middle = begin + ((end - begin) >> 1);
  89. BOOST_CONTRACT_CHECK(*begin <= *middle || value < *middle ||
  90. *middle < value);
  91. if(value < *middle) end = middle;
  92. else if(value > *middle) begin = middle + 1;
  93. else return result = middle;
  94. }
  95. return result = last;
  96. }
  97. int main() {
  98. vector<char> v;
  99. v.insert(v.begin() + 0, 'a');
  100. v.insert(v.begin() + 1, 'b');
  101. v.insert(v.begin() + 2, 'c');
  102. vector<char>::iterator i = random_binary_search(v.begin(), v.end(), 'b');
  103. assert(i != v.end());
  104. assert(*i == 'b');
  105. vector<char> w;
  106. w.insert(w.begin() + 0, 'x');
  107. w.insert(w.begin() + 1, 'y');
  108. w.swap(v);
  109. assert(*(w.begin() + 0) == 'a');
  110. assert(*(w.begin() + 1) == 'b');
  111. assert(*(w.begin() + 2) == 'c');
  112. return 0;
  113. }