overload.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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 public function overloads.
  6. #include "../detail/oteststream.hpp"
  7. #include <boost/contract/public_function.hpp>
  8. #include <boost/contract/base_types.hpp>
  9. #include <boost/contract/override.hpp>
  10. #include <boost/contract/check.hpp>
  11. #include <boost/detail/lightweight_test.hpp>
  12. #include <sstream>
  13. #include <string>
  14. boost::contract::test::detail::oteststream out;
  15. struct b {
  16. static void static_invariant() { out << "b::static_inv" << std::endl; }
  17. void invariant() const { out << "b::inv" << std::endl; }
  18. virtual void f(int /* x */, boost::contract::virtual_* v = 0) {
  19. boost::contract::check c = boost::contract::public_function(v, this)
  20. .precondition([] { out << "b::f(int)::pre" << std::endl; })
  21. .old([] { out << "b::f(int)::old" << std::endl; })
  22. .postcondition([] { out << "b::f(int)::post" << std::endl; })
  23. ;
  24. out << "b::f(int)::body" << std::endl;
  25. }
  26. virtual void f(char const* /* x */, boost::contract::virtual_* v = 0) {
  27. boost::contract::check c = boost::contract::public_function(v, this)
  28. .precondition([] { out << "b::f(char const*)::pre" << std::endl; })
  29. .old([] { out << "b::f(char const*)::old" << std::endl; })
  30. .postcondition(
  31. [] { out << "b::f(char const*)::post" << std::endl; })
  32. ;
  33. out << "b::f(char const*)::body" << std::endl;
  34. }
  35. virtual void f(int /* x */, int /* y */, boost::contract::virtual_* v = 0) {
  36. boost::contract::check c = boost::contract::public_function(v, this)
  37. .precondition([] { out << "b::f(int, int)::pre" << std::endl; })
  38. .old([] { out << "b::f(int, int)::old" << std::endl; })
  39. .postcondition([] { out << "b::f(int, int)::post" << std::endl; })
  40. ;
  41. out << "b::f(int, int)::body" << std::endl;
  42. }
  43. virtual void f(boost::contract::virtual_* v = 0) {
  44. boost::contract::check c = boost::contract::public_function(v, this)
  45. .precondition([] { out << "b::f()::pre" << std::endl; })
  46. .old([] { out << "b::f()::old" << std::endl; })
  47. .postcondition([] { out << "b::f()::post" << std::endl; })
  48. ;
  49. out << "b::f()::body" << std::endl;
  50. }
  51. void f(int /* x */[2][3], boost::contract::virtual_* v = 0) {
  52. boost::contract::check c = boost::contract::public_function(v, this)
  53. .precondition([] { out << "b::f(int[2][3])::pre" << std::endl; })
  54. .old([] { out << "b::f(int[2][3])::old" << std::endl; })
  55. .postcondition([] { out << "b::f(int[2][3])::post" << std::endl; })
  56. ;
  57. out << "b::f(int[2][3])::body" << std::endl;
  58. }
  59. void f(void (* /* x */)(int), boost::contract::virtual_* v = 0) {
  60. boost::contract::check c = boost::contract::public_function(v, this)
  61. .precondition(
  62. [] { out << "b::f(void (*)(int))::pre" << std::endl; })
  63. .old(
  64. [] { out << "b::f(void (*)(int))::old" << std::endl; })
  65. .postcondition(
  66. [] { out << "b::f(void (*)(int))::post" << std::endl; })
  67. ;
  68. out << "b::f(void (*)(int))::body" << std::endl;
  69. }
  70. };
  71. struct a
  72. #define BASES public b
  73. : BASES
  74. {
  75. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  76. #undef BASES
  77. static void static_invariant() { out << "a::static_inv" << std::endl; }
  78. void invariant() const { out << "a::inv" << std::endl; }
  79. void f(int x, boost::contract::virtual_* v = 0) /* override */ {
  80. boost::contract::check c = boost::contract::public_function<override_f>(
  81. v,
  82. static_cast<void (a::*)(int, boost::contract::virtual_*)>(&a::f),
  83. this, x
  84. )
  85. .precondition([] { out << "a::f(int)::pre" << std::endl; })
  86. .old([] { out << "a::f(int)::old" << std::endl; })
  87. .postcondition([] { out << "a::f(int)::post" << std::endl; })
  88. ;
  89. out << "a::f(int)::body" << std::endl;
  90. }
  91. // Test overload via argument type.
  92. void f(char const* x, boost::contract::virtual_* v = 0) /* override */ {
  93. boost::contract::check c = boost::contract::public_function<override_f>(
  94. v,
  95. static_cast<void (a::*)(char const*, boost::contract::virtual_*)>(
  96. &a::f),
  97. this, x
  98. )
  99. .precondition([] { out << "a::f(char const*)::pre" << std::endl; })
  100. .old([] { out << "a::f(char const*)::old" << std::endl; })
  101. .postcondition(
  102. [] { out << "a::f(char const*)::post" << std::endl; })
  103. ;
  104. out << "a::f(char const*)::body" << std::endl;
  105. }
  106. // Test overload via argument count.
  107. void f(int x, int y, boost::contract::virtual_* v = 0) /* override */ {
  108. boost::contract::check c = boost::contract::public_function<override_f>(
  109. v,
  110. static_cast<void (a::*)(int, int, boost::contract::virtual_*)>(
  111. &a::f),
  112. this, x, y
  113. )
  114. .precondition([] { out << "a::f(int, int)::pre" << std::endl; })
  115. .old([] { out << "a::f(int, int)::old" << std::endl; })
  116. .postcondition([] { out << "a::f(int, int)::post" << std::endl; })
  117. ;
  118. out << "a::f(int, int)::body" << std::endl;
  119. }
  120. // Test overload via template argument type.
  121. template<typename T>
  122. void f(T /* x */) { // Template cannot be virtual (or override) in C++.
  123. boost::contract::check c = boost::contract::public_function(this)
  124. .precondition([] { out << "a::f(T)::pre" << std::endl; })
  125. .old([] { out << "a::f(T)::old" << std::endl; })
  126. .postcondition([] { out << "a::f(T)::post" << std::endl; })
  127. ;
  128. out << "a::f(T)::body" << std::endl;
  129. }
  130. // Test no overload ambiguity in public_function called by these two cases.
  131. // NOTE: In *all* other cases, public_function is always called with a
  132. // different number of arguments so there cannot be ambiguity either
  133. // (0 args for static, 1 arg for non-virtual, 2 or 3 args for virtual,
  134. // >= 3 for override, so only in cases below of 3 args for virtual and 3
  135. // for override there could be ambiguity but there is not because of
  136. // presence or absence of override_... template parameter).
  137. typedef void (a::* f0_ptr)(boost::contract::virtual_*);
  138. void f(boost::contract::virtual_* v = 0) /* override */ {
  139. f0_ptr f0 = static_cast<f0_ptr>(&a::f);
  140. // Test this and public_function call in func below both take same 3
  141. // args but they are ambiguous because of presence override_f.
  142. boost::contract::check c = boost::contract::public_function<override_f>(
  143. v, f0, this)
  144. .precondition([] { out << "a::f()::pre" << std::endl; })
  145. .old([] { out << "a::f()::old" << std::endl; })
  146. .postcondition([] { out << "a::f()::post" << std::endl; })
  147. ;
  148. out << "a::f()::body" << std::endl;
  149. }
  150. virtual f0_ptr f(bool /* x */, boost::contract::virtual_* v = 0)
  151. /* not an override */ {
  152. f0_ptr f0 = static_cast<f0_ptr>(&a::f);
  153. // Test this and public_function call in func above both take same 3
  154. // args but they are ambiguous because of lack of override_f.
  155. boost::contract::check c = boost::contract::public_function(
  156. v, f0, this)
  157. .precondition([] { out << "a::f(bool)::pre" << std::endl; })
  158. .old([] { out << "a::f(bool)::old" << std::endl; })
  159. .postcondition([] (f0_ptr const&) {
  160. out << "a::f(bool)::post" << std::endl; })
  161. ;
  162. out << "a::f(bool)::body" << std::endl;
  163. return f0;
  164. }
  165. // Test overload with array parameter.
  166. void f(int x[2][3], boost::contract::virtual_* v = 0) /* override */ {
  167. boost::contract::check c = boost::contract::public_function<override_f>(
  168. v,
  169. static_cast<void (a::*)(int[2][3], boost::contract::virtual_*)>(
  170. &a::f),
  171. this, x
  172. )
  173. .precondition([] { out << "a::f(int[2][3])::pre" << std::endl; })
  174. .old([] { out << "a::f(int[2][3])::old" << std::endl; })
  175. .postcondition([] { out << "a::f(int[2][3])::post" << std::endl; })
  176. ;
  177. out << "a::f(int[2][3])::body" << std::endl;
  178. }
  179. // Test overload with function pointer parameter.
  180. void f(void (*x)(int), boost::contract::virtual_* v = 0) /* override */ {
  181. boost::contract::check c = boost::contract::public_function<override_f>(
  182. v,
  183. static_cast<void (a::*)(void (*)(int), boost::contract::virtual_*)>(
  184. &a::f),
  185. this, x
  186. )
  187. .precondition(
  188. [] { out << "a::f(void (*)(int))::pre" << std::endl; })
  189. .old(
  190. [] { out << "a::f(void (*)(int))::old" << std::endl; })
  191. .postcondition(
  192. [] { out << "a::f(void (*)(int))::post" << std::endl; })
  193. ;
  194. out << "a::f(void (*)(int))::body" << std::endl;
  195. }
  196. BOOST_CONTRACT_OVERRIDE(f)
  197. };
  198. void g(int) {}
  199. std::string ok_args(std::string const& args) {
  200. std::ostringstream ok; ok
  201. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  202. << "b::static_inv" << std::endl
  203. << "b::inv" << std::endl
  204. << "a::static_inv" << std::endl
  205. << "a::inv" << std::endl
  206. #endif
  207. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  208. << "b::f(" << args << ")::pre" << std::endl
  209. #endif
  210. #ifndef BOOST_CONTRACT_NO_OLDS
  211. << "b::f(" << args << ")::old" << std::endl
  212. << "a::f(" << args << ")::old" << std::endl
  213. #endif
  214. << "a::f(" << args << ")::body" << std::endl
  215. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  216. << "b::static_inv" << std::endl
  217. << "b::inv" << std::endl
  218. << "a::static_inv" << std::endl
  219. << "a::inv" << std::endl
  220. #endif
  221. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  222. << "b::f(" << args << ")::old" << std::endl
  223. << "b::f(" << args << ")::post" << std::endl
  224. << "a::f(" << args << ")::post" << std::endl
  225. #endif
  226. ;
  227. return ok.str();
  228. }
  229. int main() {
  230. std::ostringstream ok;
  231. a aa;
  232. out.str("");
  233. aa.f(123);
  234. ok.str(""); ok << ok_args("int");
  235. BOOST_TEST(out.eq(ok.str()));
  236. out.str("");
  237. aa.f("abc");
  238. ok.str(""); ok << ok_args("char const*");
  239. BOOST_TEST(out.eq(ok.str()));
  240. out.str("");
  241. aa.f(123, 456);
  242. ok.str(""); ok << ok_args("int, int");
  243. BOOST_TEST(out.eq(ok.str()));
  244. out.str("");
  245. struct {} zz;
  246. aa.f(zz); // Call template (so no override because no virtual).
  247. ok.str(""); ok
  248. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  249. << "a::static_inv" << std::endl
  250. << "a::inv" << std::endl
  251. #endif
  252. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  253. << "a::f(T)::pre" << std::endl
  254. #endif
  255. #ifndef BOOST_CONTRACT_NO_OLDS
  256. << "a::f(T)::old" << std::endl
  257. #endif
  258. << "a::f(T)::body" << std::endl
  259. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  260. << "a::static_inv" << std::endl
  261. << "a::inv" << std::endl
  262. #endif
  263. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  264. << "a::f(T)::post" << std::endl
  265. #endif
  266. ;
  267. BOOST_TEST(out.eq(ok.str()));
  268. out.str("");
  269. aa.f();
  270. ok.str(""); ok << ok_args("");
  271. BOOST_TEST(out.eq(ok.str()));
  272. out.str("");
  273. aa.f(true); // This does not override (public_function ambiguity testing).
  274. ok.str(""); ok
  275. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  276. << "a::static_inv" << std::endl
  277. << "a::inv" << std::endl
  278. #endif
  279. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  280. << "a::f(bool)::pre" << std::endl
  281. #endif
  282. #ifndef BOOST_CONTRACT_NO_OLDS
  283. << "a::f(bool)::old" << std::endl
  284. #endif
  285. << "a::f(bool)::body" << std::endl
  286. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  287. << "a::static_inv" << std::endl
  288. << "a::inv" << std::endl
  289. #endif
  290. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  291. << "a::f(bool)::post" << std::endl
  292. #endif
  293. ;
  294. BOOST_TEST(out.eq(ok.str()));
  295. out.str("");
  296. int i[2][3];
  297. aa.f(i);
  298. ok.str(""); ok << ok_args("int[2][3]");
  299. BOOST_TEST(out.eq(ok.str()));
  300. out.str("");
  301. aa.f(&g);
  302. ok.str(""); ok << ok_args("void (*)(int)");
  303. BOOST_TEST(out.eq(ok.str()));
  304. return boost::report_errors();
  305. }