virtual_access.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. // Test overrides with mixed access level from (single) base.
  6. #include "../detail/oteststream.hpp"
  7. #include <boost/contract/public_function.hpp>
  8. #include <boost/contract/function.hpp>
  9. #include <boost/contract/base_types.hpp>
  10. #include <boost/contract/override.hpp>
  11. #include <boost/contract/check.hpp>
  12. #include <boost/detail/lightweight_test.hpp>
  13. #include <sstream>
  14. boost::contract::test::detail::oteststream out;
  15. struct b { // Test all access levels (public, protected, and private).
  16. friend void call(b& me) { // Test polymorphic calls (object by &).
  17. me.f();
  18. me.g();
  19. me.h();
  20. }
  21. static void statci_inv() { out << "b::static_inv" << std::endl; }
  22. void invariant() const { out << "b::inv" << std::endl; }
  23. virtual void f(boost::contract::virtual_* v = 0) {
  24. boost::contract::check c = boost::contract::public_function(v, this)
  25. .precondition([] { out << "b::f::pre" << std::endl; })
  26. .old([] { out << "b::f::old" << std::endl; })
  27. .postcondition([] { out << "b::f::post" << std::endl; })
  28. ;
  29. out << "b::f::body" << std::endl;
  30. }
  31. // NOTE: Both protected and private virtual members must declare
  32. // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in
  33. // derived classes with contracts because C++ uses also default parameters
  34. // to match signature of overriding functions).
  35. protected:
  36. virtual void g(boost::contract::virtual_* /* v */= 0) {
  37. boost::contract::check c = boost::contract::function()
  38. .precondition([] { out << "b::g::pre" << std::endl; })
  39. .old([] { out << "b::g::old" << std::endl; })
  40. .postcondition([] { out << "b::g::post" << std::endl; })
  41. ;
  42. out << "b::g::body" << std::endl;
  43. }
  44. private:
  45. virtual void h(boost::contract::virtual_* /* v */ = 0) {
  46. boost::contract::check c = boost::contract::function()
  47. .precondition([] { out << "b::h::pre" << std::endl; })
  48. .old([] { out << "b::h::old" << std::endl; })
  49. .postcondition([] { out << "b::h::post" << std::endl; })
  50. ;
  51. out << "b::h::body" << std::endl;
  52. }
  53. };
  54. struct a // Test overrides with mixed access levels from base.
  55. #define BASES public b
  56. : BASES
  57. {
  58. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  59. #undef BASES
  60. static void statci_inv() { out << "a::static_inv" << std::endl; }
  61. void invariant() const { out << "a::inv" << std::endl; }
  62. virtual void f(boost::contract::virtual_* v = 0) /* override */ {
  63. boost::contract::check c = boost::contract::public_function<override_f>(
  64. v, &a::f, this)
  65. .precondition([] { out << "a::f::pre" << std::endl; })
  66. .old([] { out << "a::f::old" << std::endl; })
  67. .postcondition([] { out << "a::f::post" << std::endl; })
  68. ;
  69. out << "a::f::body" << std::endl;
  70. }
  71. BOOST_CONTRACT_OVERRIDES(f)
  72. // Following do not override public members so no `override_...` param and
  73. // they do not actually subcontract.
  74. virtual void g(boost::contract::virtual_* v = 0) /* override */ {
  75. boost::contract::check c = boost::contract::public_function(v, this)
  76. .precondition([] { out << "a::g::pre" << std::endl; })
  77. .old([] { out << "a::g::old" << std::endl; })
  78. .postcondition([] { out << "a::g::post" << std::endl; })
  79. ;
  80. out << "a::g::body" << std::endl;
  81. }
  82. virtual void h(boost::contract::virtual_* v = 0) /* override */ {
  83. boost::contract::check c = boost::contract::public_function(v, this)
  84. .precondition([] { out << "a::h::pre" << std::endl; })
  85. .old([] { out << "a::h::old" << std::endl; })
  86. .postcondition([] { out << "a::h::post" << std::endl; })
  87. ;
  88. out << "a::h::body" << std::endl;
  89. }
  90. };
  91. int main() {
  92. std::ostringstream ok;
  93. b bb;
  94. out.str("");
  95. call(bb);
  96. ok.str(""); ok
  97. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  98. << "b::inv" << std::endl
  99. #endif
  100. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  101. << "b::f::pre" << std::endl
  102. #endif
  103. #ifndef BOOST_CONTRACT_NO_OLDS
  104. << "b::f::old" << std::endl
  105. #endif
  106. << "b::f::body" << std::endl
  107. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  108. << "b::inv" << std::endl
  109. #endif
  110. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  111. << "b::f::post" << std::endl
  112. #endif
  113. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  114. << "b::g::pre" << std::endl
  115. #endif
  116. #ifndef BOOST_CONTRACT_NO_OLDS
  117. << "b::g::old" << std::endl
  118. #endif
  119. << "b::g::body" << std::endl
  120. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  121. << "b::g::post" << std::endl
  122. #endif
  123. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  124. << "b::h::pre" << std::endl
  125. #endif
  126. #ifndef BOOST_CONTRACT_NO_OLDS
  127. << "b::h::old" << std::endl
  128. #endif
  129. << "b::h::body" << std::endl
  130. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  131. << "b::h::post" << std::endl
  132. #endif
  133. ;
  134. BOOST_TEST(out.eq(ok.str()));
  135. a aa;
  136. out.str("");
  137. call(aa);
  138. ok.str(""); ok
  139. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  140. << "b::inv" << std::endl
  141. << "a::inv" << std::endl
  142. #endif
  143. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  144. << "b::f::pre" << std::endl
  145. #endif
  146. #ifndef BOOST_CONTRACT_NO_OLDS
  147. << "b::f::old" << std::endl
  148. << "a::f::old" << std::endl
  149. #endif
  150. << "a::f::body" << std::endl
  151. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  152. << "b::inv" << std::endl
  153. << "a::inv" << std::endl
  154. #endif
  155. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  156. << "b::f::old" << std::endl
  157. << "b::f::post" << std::endl
  158. << "a::f::post" << std::endl
  159. #endif
  160. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  161. << "a::inv" << std::endl
  162. #endif
  163. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  164. << "a::g::pre" << std::endl
  165. #endif
  166. #ifndef BOOST_CONTRACT_NO_OLDS
  167. << "a::g::old" << std::endl
  168. #endif
  169. << "a::g::body" << std::endl
  170. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  171. << "a::inv" << std::endl
  172. #endif
  173. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  174. << "a::g::post" << std::endl
  175. #endif
  176. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  177. << "a::inv" << std::endl
  178. #endif
  179. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  180. << "a::h::pre" << std::endl
  181. #endif
  182. #ifndef BOOST_CONTRACT_NO_OLDS
  183. << "a::h::old" << std::endl
  184. #endif
  185. << "a::h::body" << std::endl
  186. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  187. << "a::inv" << std::endl
  188. #endif
  189. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  190. << "a::h::post" << std::endl
  191. #endif
  192. ;
  193. BOOST_TEST(out.eq(ok.str()));
  194. return boost::report_errors();
  195. }