private_protected_virtual.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 <limits>
  7. #include <cassert>
  8. //[private_protected_virtual_counter
  9. class counter {
  10. // Virtual private and protected functions still declare extra
  11. // `virtual_* = 0` parameter (otherwise they cannot be overridden), but...
  12. protected:
  13. virtual void set(int n, boost::contract::virtual_* = 0) {
  14. boost::contract::check c = boost::contract::function() // ...no `v`.
  15. .precondition([&] {
  16. BOOST_CONTRACT_ASSERT(n <= 0);
  17. })
  18. .postcondition([&] {
  19. BOOST_CONTRACT_ASSERT(get() == n);
  20. })
  21. ;
  22. n_ = n;
  23. }
  24. private:
  25. virtual void dec(boost::contract::virtual_* = 0) {
  26. boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(get()); // ...no `v`.
  27. boost::contract::check c = boost::contract::function() // ...no `v`.
  28. .precondition([&] {
  29. BOOST_CONTRACT_ASSERT(
  30. get() + 1 >= std::numeric_limits<int>::min());
  31. })
  32. .postcondition([&] {
  33. BOOST_CONTRACT_ASSERT(get() == *old_get - 1);
  34. })
  35. ;
  36. set(get() - 1);
  37. }
  38. int n_;
  39. /* ... */
  40. //]
  41. public:
  42. virtual int get(boost::contract::virtual_* v = 0) const {
  43. int result;
  44. boost::contract::check c = boost::contract::public_function(
  45. v, result, this)
  46. .postcondition([&] (int const result) {
  47. BOOST_CONTRACT_ASSERT(result <= 0);
  48. BOOST_CONTRACT_ASSERT(result == n_);
  49. })
  50. ;
  51. return result = n_;
  52. }
  53. counter() : n_(0) {} // Should contract constructor and destructor too.
  54. void invariant() const {
  55. BOOST_CONTRACT_ASSERT(get() <= 0);
  56. }
  57. friend int main();
  58. };
  59. //[private_protected_virtual_counter10
  60. class counter10
  61. #define BASES public counter
  62. : BASES
  63. {
  64. public:
  65. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  66. #undef BASES
  67. // Overriding from non-public members so no subcontracting, no override_...
  68. virtual void set(int n, boost::contract::virtual_* v = 0) /* override */ {
  69. boost::contract::check c = boost::contract::public_function(v, this)
  70. .precondition([&] {
  71. BOOST_CONTRACT_ASSERT(n % 10 == 0);
  72. })
  73. .postcondition([&] {
  74. BOOST_CONTRACT_ASSERT(get() == n);
  75. })
  76. ;
  77. counter::set(n);
  78. }
  79. virtual void dec(boost::contract::virtual_* v = 0) /* override */ {
  80. boost::contract::old_ptr<int> old_get = BOOST_CONTRACT_OLDOF(v, get());
  81. boost::contract::check c = boost::contract::public_function(v, this)
  82. .precondition([&] {
  83. BOOST_CONTRACT_ASSERT(
  84. get() + 10 >= std::numeric_limits<int>::min());
  85. })
  86. .postcondition([&] {
  87. BOOST_CONTRACT_ASSERT(get() == *old_get - 10);
  88. })
  89. ;
  90. set(get() - 10);
  91. }
  92. /* ... */
  93. //]
  94. virtual int get(boost::contract::virtual_* v = 0) const {
  95. int result;
  96. boost::contract::check c = boost::contract::public_function<
  97. override_get>(v, result, &counter10::get, this);
  98. return result = counter::get();
  99. }
  100. BOOST_CONTRACT_OVERRIDE(get)
  101. // Should contract default constructor and destructor too.
  102. void invariant() const {
  103. BOOST_CONTRACT_ASSERT(get() % 10 == 0);
  104. }
  105. };
  106. int main() {
  107. counter cnt;
  108. assert(cnt.get() == 0);
  109. cnt.dec();
  110. assert(cnt.get() == -1);
  111. counter10 cnt10;
  112. counter& b = cnt10; // Polymorphic calls.
  113. assert(b.get() == 0);
  114. b.dec();
  115. assert(b.get() == -10);
  116. return 0;
  117. }