overload.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 <boost/optional.hpp>
  7. #include <string>
  8. #include <sstream>
  9. #include <cassert>
  10. class lines {
  11. public:
  12. virtual std::string str(boost::contract::virtual_* v = 0) const = 0;
  13. virtual std::string& str(boost::contract::virtual_* v = 0) = 0;
  14. virtual void put(std::string const& x,
  15. boost::contract::virtual_* v = 0) = 0;
  16. virtual void put(char x, boost::contract::virtual_* v = 0) = 0;
  17. virtual void put(int x, bool tab = false,
  18. boost::contract::virtual_* v = 0) = 0;
  19. };
  20. std::string lines::str(boost::contract::virtual_* v) const {
  21. std::string result;
  22. boost::contract::check c = boost::contract::public_function(v, result, this)
  23. .postcondition([&] (std::string const& result) {
  24. if(result != "") BOOST_CONTRACT_ASSERT(*result.rbegin() == '\n');
  25. })
  26. ;
  27. assert(false);
  28. return result;
  29. }
  30. std::string& lines::str(boost::contract::virtual_* v) {
  31. boost::optional<std::string&> result;
  32. boost::contract::check c = boost::contract::public_function(v, result, this)
  33. .postcondition([&] (boost::optional<std::string const&> const& result) {
  34. if(*result != "") BOOST_CONTRACT_ASSERT(*result->rbegin() == '\n');
  35. })
  36. ;
  37. assert(false);
  38. return *result;
  39. }
  40. void lines::put(std::string const& x, boost::contract::virtual_* v) {
  41. boost::contract::check c = boost::contract::public_function(v, this)
  42. .precondition([&] {
  43. BOOST_CONTRACT_ASSERT(*x.rbegin() != '\n');
  44. })
  45. ;
  46. assert(false);
  47. }
  48. void lines::put(char x, boost::contract::virtual_* v) {
  49. boost::contract::check c = boost::contract::public_function(v, this)
  50. .precondition([&] {
  51. BOOST_CONTRACT_ASSERT(x != '\n');
  52. })
  53. ;
  54. assert(false);
  55. }
  56. void lines::put(int x, bool tab,
  57. boost::contract::virtual_* v) {
  58. boost::contract::check c = boost::contract::public_function(v, this)
  59. .precondition([&] {
  60. BOOST_CONTRACT_ASSERT(x >= 0);
  61. })
  62. ;
  63. assert(false);
  64. }
  65. //[overload
  66. class string_lines
  67. #define BASES public lines
  68. : BASES
  69. {
  70. public:
  71. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  72. #undef BASES
  73. BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads.
  74. std::string str(boost::contract::virtual_* v = 0) const /* override */ {
  75. std::string result;
  76. boost::contract::check c = boost::contract::public_function<
  77. override_str>(
  78. v, result,
  79. // `static_cast` resolves overloaded function pointer ambiguities.
  80. static_cast<std::string (string_lines::*)(
  81. boost::contract::virtual_*) const>(&string_lines::str),
  82. this
  83. );
  84. return result = str_;
  85. }
  86. // Overload on (absence of) `const` qualifier.
  87. std::string& str(boost::contract::virtual_* v = 0) /* override */ {
  88. boost::contract::check c = boost::contract::public_function<
  89. override_str>(
  90. v, str_,
  91. // `static_cast` resolves overloaded function pointer ambiguities.
  92. static_cast<std::string& (string_lines::*)(
  93. boost::contract::virtual_*)>(&string_lines::str),
  94. this
  95. );
  96. return str_;
  97. }
  98. BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads.
  99. void put(std::string const& x,
  100. boost::contract::virtual_* v = 0) /* override */ {
  101. boost::contract::old_ptr<std::string> old_str =
  102. BOOST_CONTRACT_OLDOF(v, str());
  103. boost::contract::check c = boost::contract::public_function<
  104. override_put>(
  105. v,
  106. // `static_cast` resolves overloaded function pointer ambiguities.
  107. static_cast<void (string_lines::*)(std::string const&,
  108. boost::contract::virtual_*)>(&string_lines::put),
  109. this, x
  110. )
  111. .postcondition([&] {
  112. BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
  113. })
  114. ;
  115. str_ = str_ + x + '\n';
  116. }
  117. // Overload on argument type.
  118. void put(char x, boost::contract::virtual_* v = 0) /* override */ {
  119. boost::contract::old_ptr<std::string> old_str =
  120. BOOST_CONTRACT_OLDOF(v, str());
  121. boost::contract::check c = boost::contract::public_function<
  122. override_put>(
  123. v,
  124. // `static_cast` resolves overloaded function pointer ambiguities.
  125. static_cast<void (string_lines::*)(char,
  126. boost::contract::virtual_*)>(&string_lines::put),
  127. this, x
  128. )
  129. .postcondition([&] {
  130. BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
  131. })
  132. ;
  133. str_ = str_ + x + '\n';
  134. }
  135. // Overload on argument type and arity (also with default parameter).
  136. void put(int x, bool tab = false,
  137. boost::contract::virtual_* v = 0) /* override */ {
  138. boost::contract::old_ptr<std::string> old_str =
  139. BOOST_CONTRACT_OLDOF(v, str());
  140. boost::contract::check c = boost::contract::public_function<
  141. override_put>(
  142. v,
  143. // `static_cast` resolves overloaded function pointer ambiguities.
  144. static_cast<void (string_lines::*)(int, bool,
  145. boost::contract::virtual_*)>(&string_lines::put),
  146. this, x, tab
  147. )
  148. .postcondition([&] {
  149. std::ostringstream s;
  150. s << x;
  151. BOOST_CONTRACT_ASSERT(
  152. str() == *old_str + (tab ? "\t" : "") + s.str() + '\n');
  153. })
  154. ;
  155. std::ostringstream s;
  156. s << str_ << (tab ? "\t" : "") << x << '\n';
  157. str_ = s.str();
  158. }
  159. private:
  160. std::string str_;
  161. };
  162. //]
  163. int main() {
  164. string_lines s;
  165. s.put("abc");
  166. assert(s.str() == "abc\n");
  167. s.put('x');
  168. assert(s.str() == "abc\nx\n");
  169. s.put(10);
  170. assert(s.str() == "abc\nx\n10\n");
  171. s.put(20, true);
  172. lines const& l = s;
  173. assert(l.str() == "abc\nx\n10\n\t20\n");
  174. return 0;
  175. }