check.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #ifndef BOOST_CONTRACT_CHECK_HPP_
  2. #define BOOST_CONTRACT_CHECK_HPP_
  3. // Copyright (C) 2008-2018 Lorenzo Caminiti
  4. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  5. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  6. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  7. /** @file
  8. RAII object that checks contracts.
  9. */
  10. #include <boost/contract/core/config.hpp>
  11. #include <boost/contract/core/check_macro.hpp>
  12. #include <boost/contract/core/specify.hpp>
  13. #include <boost/contract/core/exception.hpp> // For set_... (if always in code).
  14. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  15. defined(BOOST_CONTRACT_STATIC_LINK)
  16. #include <boost/contract/detail/condition/cond_base.hpp>
  17. #include <boost/contract/detail/auto_ptr.hpp>
  18. #include <boost/contract/detail/debug.hpp>
  19. #endif
  20. #include <boost/contract/detail/check.hpp>
  21. #include <boost/config.hpp>
  22. /* PRIVATE */
  23. /** @cond */
  24. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  25. defined(BOOST_CONTRACT_STATIC_LINK)
  26. #define BOOST_CONTRACT_CHECK_CTOR_DEF_(contract_type) \
  27. : cond_(const_cast<contract_type&>(contract).cond_.release()) \
  28. { \
  29. BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
  30. cond_->initialize(); \
  31. }
  32. #else
  33. #define BOOST_CONTRACT_CHECK_CTOR_DEF_(contract_type) {}
  34. #endif
  35. /** @endcond */
  36. /* CODE */
  37. namespace boost { namespace contract {
  38. /**
  39. RAII object that checks the contracts.
  40. In general, when this object is constructed it checks class invariants at entry,
  41. preconditions, and makes old value copies at body.
  42. When it is destructed, it checks class invariants at exist, postconditions, and
  43. exception guarantees.
  44. This object enforces the following (see
  45. @RefSect{contract_programming_overview, Contract Programming Overview}):
  46. @li Postconditions are checked only if the body does not throw an exception.
  47. @li Exceptions guarantees are checked only if the body throws an exception.
  48. @li Constructor entry never checks class invariants.
  49. @li Destructor exit checks class invariants only if the body throws an
  50. exception (even if destructors should usually not be programmed to throw
  51. exceptions in C++ and they are implicitly declared @c noexcept since C++11).
  52. @li Static invariants are always checked at entry and exit (and regardless of
  53. the body throwing exceptions or not).
  54. When used this way, this object is constructed and initialized to the return
  55. value of one of the contract functions @RefFunc{boost::contract::function},
  56. @RefFunc{boost::contract::constructor}, @RefFunc{boost::contract::destructor},
  57. or @RefFunc{boost::contract::public_function}.
  58. In addition to that, this object can be constructed from a nullary functor when
  59. it is used to program implementation checks.
  60. @see @RefSect{tutorial, Tutorial},
  61. @RefSect{advanced.implementation_checks, Implementation Checks}
  62. */
  63. class check { // Copy ctor only (as move via ptr release).
  64. public:
  65. // NOTE: Unfortunately, Apple compilers define a `check(...)` macro that
  66. // clashes with the name of this class. In the following code,
  67. // BOOST_PREVENT_MACRO_SUBSTITUTION is used to workaround these name
  68. // clashes. In user code, `check c = ...` syntax is typically used also
  69. // avoiding clashes.
  70. /**
  71. Construct this object for implementation checks.
  72. This can be used to program checks within implementation code (body, etc.).
  73. This constructor is not declared @c explicit so initializations can use
  74. assignment syntax @c =.
  75. @b Throws: This can throw in case programmers specify contract failure
  76. handlers that throw exceptions instead of terminating the
  77. program (see
  78. @RefSect{advanced.throw_on_failures__and__noexcept__,
  79. Throw on Failure}).
  80. @param f Nullary functor that asserts implementation checks. @c f() will
  81. be called as soon as this object is constructed at the point it
  82. is declared within the implementation code (see
  83. @RefSect{advanced.implementation_checks,
  84. Implementation Checks}).
  85. */
  86. template<typename F> // Cannot check `if(f) ...` as f can be a lambda.
  87. // f must be a valid callable object (not null func ptr, empty ftor, etc.
  88. /* implicit */ check
  89. /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  90. F const& f) {
  91. BOOST_CONTRACT_DETAIL_CHECK({ f(); })
  92. }
  93. /**
  94. Construct this object copying it from the specified one.
  95. This object will check the contract, the copied-from object will not (i.e.,
  96. contract check ownership is transferred from the copied object to the new
  97. object being created by this constructor).
  98. @param other Copied-from object.
  99. */
  100. check /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  101. check const& other)
  102. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  103. defined(BOOST_CONTRACT_STATIC_LINK)
  104. // Copy ctor moves cond_ pointer to dest.
  105. : cond_(const_cast<check&>(other).cond_.release())
  106. #endif
  107. {}
  108. /**
  109. Construct this object to check the specified contract.
  110. This checks class invariants at entry (if those were specified for the given
  111. contract).
  112. This constructor is not declared @c explicit so initializations can use
  113. assignment syntax @c =.
  114. @b Throws: This can throw in case programmers specify contract failure
  115. handlers that throw exceptions instead of terminating the
  116. program (see
  117. @RefSect{advanced.throw_on_failures__and__noexcept__,
  118. Throw on Failure}).
  119. @param contract Contract to be checked (usually the return value of
  120. @RefFunc{boost::contract::function} or
  121. @RefFunc{boost::contract::public_function}).
  122. @tparam VirtualResult Return type of the enclosing function declaring the
  123. contract if that is either a virtual or an
  124. overriding public function, otherwise this is always
  125. @c void.
  126. (Usually this template parameter is automatically
  127. deduced by C++ and it does not need to be explicitly
  128. specified by programmers.)
  129. */
  130. template<typename VirtualResult>
  131. /* implicit */ check
  132. /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  133. specify_precondition_old_postcondition_except<VirtualResult> const&
  134. contract
  135. )
  136. #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
  137. BOOST_CONTRACT_CHECK_CTOR_DEF_(
  138. specify_precondition_old_postcondition_except<VirtualResult>)
  139. #else
  140. ;
  141. #endif
  142. /**
  143. Construct this object to check the specified contract.
  144. This checks class invariants at entry and preconditions (if any of those
  145. were specified for the given contract).
  146. This constructor is not declared @c explicit so initializations can use
  147. assignment syntax @c =.
  148. @b Throws: This can throw in case programmers specify contract failure
  149. handlers that throw exceptions instead of terminating the
  150. program (see
  151. @RefSect{advanced.throw_on_failures__and__noexcept__,
  152. Throw on Failure}).
  153. @param contract Contract to be checked (usually the return value of
  154. @RefFunc{boost::contract::function},
  155. @RefFunc{boost::contract::constructor},
  156. @RefFunc{boost::contract::destructor}, or
  157. @RefFunc{boost::contract::public_function}).
  158. @tparam VirtualResult Return type of the enclosing function declaring the
  159. contract if that is either a virtual or an
  160. overriding public function, otherwise this is always
  161. @c void.
  162. (Usually this template parameter is automatically
  163. deduced by C++ and it does not need to be explicitly
  164. specified by programmers.)
  165. */
  166. template<typename VirtualResult>
  167. /* implicit */ check
  168. /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  169. specify_old_postcondition_except<VirtualResult> const& contract)
  170. #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
  171. BOOST_CONTRACT_CHECK_CTOR_DEF_(
  172. specify_old_postcondition_except<VirtualResult>)
  173. #else
  174. ;
  175. #endif
  176. /**
  177. Construct this object to check the specified contract.
  178. This checks class invariants at entry and preconditions then it makes old
  179. value copies at body (if any of those were specified for the given
  180. contract).
  181. This constructor is not declared @c explicit so initializations can use
  182. assignment syntax @c =.
  183. @b Throws: This can throw in case programmers specify contract failure
  184. handlers that throw exceptions instead of terminating te
  185. program (see
  186. @RefSect{advanced.throw_on_failures__and__noexcept__,
  187. Throw on Failure}).
  188. @param contract Contract to be checked (usually the return value of
  189. @RefFunc{boost::contract::function},
  190. @RefFunc{boost::contract::constructor},
  191. @RefFunc{boost::contract::destructor}, or
  192. @RefFunc{boost::contract::public_function}).
  193. @tparam VirtualResult Return type of the enclosing function declaring the
  194. contract if that is either a virtual or an
  195. overriding public function, otherwise this is always
  196. @c void.
  197. (Usually this template parameter is automatically
  198. deduced by C++ and it does not need to be explicitly
  199. specified by programmers.)
  200. */
  201. template<typename VirtualResult>
  202. /* implicit */ check
  203. /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  204. specify_postcondition_except<VirtualResult> const& contract)
  205. #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
  206. BOOST_CONTRACT_CHECK_CTOR_DEF_(
  207. specify_postcondition_except<VirtualResult>)
  208. #else
  209. ;
  210. #endif
  211. /**
  212. Construct this object to check the specified contract.
  213. This checks class invariants at entry and preconditions then it makes old
  214. value copies at body, plus the destructor of this object will also check
  215. postconditions in this case (if any of those were specified for the given
  216. contract).
  217. This constructor is not declared @c explicit so initializations can use
  218. assignment syntax @c =.
  219. @b Throws: This can throw in case programmers specify contract failure
  220. handlers that throw exceptions instead of terminating the
  221. program (see
  222. @RefSect{advanced.throw_on_failures__and__noexcept__,
  223. Throw on Failure}).
  224. @param contract Contract to be checked (usually the return value of
  225. @RefFunc{boost::contract::function},
  226. @RefFunc{boost::contract::constructor},
  227. @RefFunc{boost::contract::destructor}, or
  228. @RefFunc{boost::contract::public_function}).
  229. @tparam VirtualResult Return type of the enclosing function declaring the
  230. contract if that is either a virtual or an
  231. overriding public function, otherwise this is always
  232. @c void.
  233. (Usually this template parameter is automatically
  234. deduced by C++ and it does not need to be explicitly
  235. specified by programmers.)
  236. */
  237. /* implicit */ check
  238. /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  239. specify_except const& contract)
  240. #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
  241. BOOST_CONTRACT_CHECK_CTOR_DEF_(specify_except)
  242. #else
  243. ;
  244. #endif
  245. /**
  246. Construct this object to check the specified contract.
  247. This checks class invariants at entry and preconditions then it makes old
  248. value copies at body, plus the destructor of this object will also check
  249. postconditions and exception guarantees in this case (if any of those were
  250. specified for the given contract).
  251. This constructor is not declared @c explicit so initializations can use
  252. assignment syntax @c =.
  253. @b Throws: This can throw in case programmers specify contract failure
  254. handlers that throw exceptions instead of terminating the
  255. program (see
  256. @RefSect{advanced.throw_on_failures__and__noexcept__,
  257. Throw on Failure}).
  258. @param contract Contract to be checked (usually the return value of
  259. @RefFunc{boost::contract::function},
  260. @RefFunc{boost::contract::constructor},
  261. @RefFunc{boost::contract::destructor}, or
  262. @RefFunc{boost::contract::public_function}).
  263. @tparam VirtualResult Return type of the enclosing function declaring the
  264. contract if that is either a virtual or an
  265. overriding public function, otherwise this is always
  266. @c void.
  267. (Usually this template parameter is automatically
  268. deduced by C++ and it does not need to be explicitly
  269. specified by programmers.)
  270. */
  271. /* implicit */ check
  272. /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
  273. specify_nothing const& contract)
  274. #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
  275. BOOST_CONTRACT_CHECK_CTOR_DEF_(specify_nothing)
  276. #else
  277. ;
  278. #endif
  279. /**
  280. Destruct this object.
  281. This checks class invariants at exit and either postconditions when the
  282. enclosing function body did not throw an exception, or exception guarantees
  283. when the function body threw an exception (if class invariants,
  284. postconditions, and exception guarantees respectively were specified for the
  285. enclosing class and the contract parameter given when constructing this
  286. object).
  287. @b Throws: This can throw in case programmers specify contract failure
  288. handlers that throw exceptions instead of terminating the
  289. program (see
  290. @RefSect{advanced.throw_on_failures__and__noexcept__,
  291. Throw on Failure}).
  292. (This is declared @c noexcept(false) since C++11.)
  293. */
  294. ~check /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ()
  295. BOOST_NOEXCEPT_IF(false) /* allow auto_ptr dtor to throw */
  296. {}
  297. /** @cond */
  298. private:
  299. check& operator=(check const&); // Cannot copy outside of `check c = ...`.
  300. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  301. defined(BOOST_CONTRACT_STATIC_LINK)
  302. boost::contract::detail::auto_ptr<boost::contract::detail::cond_base>
  303. cond_;
  304. #endif
  305. /** @endcond */
  306. };
  307. } } // namespace
  308. #endif // #include guard