2 #ifndef BOOST_CONTRACT_CHECK_HPP_
3 #define BOOST_CONTRACT_CHECK_HPP_
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
11 RAII object that checks contracts.
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>
24 #include <boost/contract/detail/check.hpp>
25 #include <boost/config.hpp>
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()) \
36 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
37 cond_->initialize(); \
40 #define BOOST_CONTRACT_CHECK_CTOR_DEF_(contract_type) {}
47 namespace boost { namespace contract {
50 RAII object that checks the contracts.
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
56 This object enforces the following (see
57 @RefSect{contract_programming_overview, Contract Programming Overview}):
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).
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.
75 @see @RefSect{tutorial, Tutorial},
76 @RefSect{advanced.implementation_checks, Implementation Checks}
78 class check { // Copy ctor only (as move via ptr release).
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
87 Construct this object for implementation checks.
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 =.
93 @b Throws: This can throw in case programmers specify contract failure
94 handlers that throw exceptions instead of terminating the
96 @RefSect{advanced.throw_on_failures__and__noexcept__,
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}).
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.
108 /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
110 BOOST_CONTRACT_DETAIL_CHECK({ f(); })
114 Construct this object copying it from the specified one.
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).
120 @param other Copied-from object.
122 check /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
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())
132 Construct this object to check the specified contract.
134 This checks class invariants at entry (if those were specified for the given
136 This constructor is not declared @c explicit so initializations can use
137 assignment syntax @c =.
139 @b Throws: This can throw in case programmers specify contract failure
140 handlers that throw exceptions instead of terminating the
142 @RefSect{advanced.throw_on_failures__and__noexcept__,
145 @param contract Contract to be checked (usually the return value of
146 @RefFunc{boost::contract::function} or
147 @RefFunc{boost::contract::public_function}).
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
153 (Usually this template parameter is automatically
154 deduced by C++ and it does not need to be explicitly
155 specified by programmers.)
157 template<typename VirtualResult>
159 /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ (
160 specify_precondition_old_postcondition_except<VirtualResult> const&
163 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
164 BOOST_CONTRACT_CHECK_CTOR_DEF_(
165 specify_precondition_old_postcondition_except<VirtualResult>)
171 Construct this object to check the specified contract.
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 =.
178 @b Throws: This can throw in case programmers specify contract failure
179 handlers that throw exceptions instead of terminating the
181 @RefSect{advanced.throw_on_failures__and__noexcept__,
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}).
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
194 (Usually this template parameter is automatically
195 deduced by C++ and it does not need to be explicitly
196 specified by programmers.)
198 template<typename VirtualResult>
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>)
210 Construct this object to check the specified contract.
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
215 This constructor is not declared @c explicit so initializations can use
216 assignment syntax @c =.
218 @b Throws: This can throw in case programmers specify contract failure
219 handlers that throw exceptions instead of terminating te
221 @RefSect{advanced.throw_on_failures__and__noexcept__,
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}).
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
234 (Usually this template parameter is automatically
235 deduced by C++ and it does not need to be explicitly
236 specified by programmers.)
238 template<typename VirtualResult>
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>)
250 Construct this object to check the specified contract.
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
256 This constructor is not declared @c explicit so initializations can use
257 assignment syntax @c =.
259 @b Throws: This can throw in case programmers specify contract failure
260 handlers that throw exceptions instead of terminating the
262 @RefSect{advanced.throw_on_failures__and__noexcept__,
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}).
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
275 (Usually this template parameter is automatically
276 deduced by C++ and it does not need to be explicitly
277 specified by programmers.)
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)
289 Construct this object to check the specified contract.
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 =.
298 @b Throws: This can throw in case programmers specify contract failure
299 handlers that throw exceptions instead of terminating the
301 @RefSect{advanced.throw_on_failures__and__noexcept__,
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}).
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
314 (Usually this template parameter is automatically
315 deduced by C++ and it does not need to be explicitly
316 specified by programmers.)
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)
328 Destruct this object.
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
337 @b Throws: This can throw in case programmers specify contract failure
338 handlers that throw exceptions instead of terminating the
340 @RefSect{advanced.throw_on_failures__and__noexcept__,
342 (This is declared @c noexcept(false) since C++11.)
344 ~check /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ()
345 BOOST_NOEXCEPT_IF(false) /* allow auto_ptr dtor to throw */
350 check& operator=(check const&); // Cannot copy outside of `check c = ...`.
352 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
353 defined(BOOST_CONTRACT_STATIC_LINK)
354 boost::contract::detail::auto_ptr<boost::contract::detail::cond_base>
362 #endif // #include guard