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