2 #ifndef BOOST_CONTRACT_SPECIFY_HPP_
3 #define BOOST_CONTRACT_SPECIFY_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 Specify preconditions, old value copies at body, postconditions, and exception
14 Preconditions, old value copies at body, postconditions, and exception
15 guarantees are all optionals but, when they are specified, they need to be
16 specified in that order.
19 #include <boost/contract/core/config.hpp>
20 #include <boost/contract/detail/decl.hpp>
21 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
22 defined(BOOST_CONTRACT_STATIC_LINK)
23 #include <boost/contract/detail/condition/cond_base.hpp>
24 #include <boost/contract/detail/condition/cond_post.hpp>
25 #include <boost/contract/detail/auto_ptr.hpp>
26 #include <boost/contract/detail/none.hpp>
28 #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
29 !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
30 !defined(BOOST_CONTRACT_NO_EXCEPTS)
31 #include <boost/contract/detail/debug.hpp>
33 #include <boost/config.hpp>
35 // NOTE: No inheritance for faster run-times (macros to avoid duplicated code).
41 // NOTE: Private copy ops below will force compile-time error is `auto c = ...`
42 // is used instead of `check c = ...` but only up to C++17. C++17 strong copy
43 // elision on function return values prevents this lib from generating a
44 // compile-time error in those cases, but the lib will still generate a run-time
45 // error according with ON_MISSING_CHECK_DECL.
46 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
47 defined(BOOST_CONTRACT_STATIC_LINK)
48 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
50 boost::contract::detail::auto_ptr<cond_type > cond_; \
51 explicit class_type(cond_type* cond) : cond_(cond) {} \
52 class_type(class_type const& other) : cond_(other.cond_) {} \
53 class_type& operator=(class_type const& other) { \
54 cond_ = other.cond_; \
58 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ cond_.release()
60 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
63 class_type(class_type const&) {} \
64 class_type& operator=(class_type const&) { return *this; }
66 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ /* nothing */
69 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
70 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
71 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
73 return specify_old_postcondition_except<VirtualResult>( \
74 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
76 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
77 return specify_old_postcondition_except<VirtualResult>( \
78 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
81 #ifndef BOOST_CONTRACT_NO_OLDS
82 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
83 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
85 return specify_postcondition_except<VirtualResult>( \
86 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
88 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
89 return specify_postcondition_except<VirtualResult>( \
90 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
93 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
94 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
95 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
97 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
99 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
100 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
103 #ifndef BOOST_CONTRACT_NO_EXCEPTS
104 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
105 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
106 cond_->set_except(f); \
107 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
109 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
110 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
121 template<typename VR>
122 class specify_precondition_old_postcondition_except;
124 template<typename VR>
125 class specify_old_postcondition_except;
127 template<typename VR>
128 class specify_postcondition_except;
130 class specify_except;
134 namespace boost { namespace contract {
137 Used to prevent setting other contract conditions after exception guarantees.
139 This class has no member function so it is used to prevent specifying additional
140 functors to check any other contract.
141 This object is internally constructed by this library when users specify
142 contracts calling @RefFunc{boost::contract::function} and similar functions
143 (that is why this class does not have a public constructor).
145 @see @RefSect{tutorial, Tutorial}
147 class specify_nothing { // Privately copyable (as *).
150 Destruct this object.
152 @b Throws: This can throw in case programmers specify failure handlers that
153 throw exceptions instead of terminating the program (see
154 @RefSect{advanced.throw_on_failures__and__noexcept__,
156 (This is declared @c noexcept(false) since C++11.)
158 ~specify_nothing() BOOST_NOEXCEPT_IF(false) {}
160 // No set member function here.
164 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_nothing,
165 boost::contract::detail::cond_base)
167 // Friends (used to limit library's public API).
171 template<typename VR>
172 friend class specify_precondition_old_postcondition_except;
174 template<typename VR>
175 friend class specify_old_postcondition_except;
177 template<typename VR>
178 friend class specify_postcondition_except;
180 friend class specify_except;
185 Allow to specify exception guarantees.
187 Allow to specify the functor this library will call to check exception
189 This object is internally constructed by this library when users specify
190 contracts calling @RefFunc{boost::contract::function} and similar functions
191 (that is why this class does not have a public constructor).
193 @see @RefSect{tutorial.exception_guarantees, Exception Guarantees}
195 class specify_except { // Privately copyable (as *).
198 Destruct this object.
200 @b Throws: This can throw in case programmers specify failure handlers that
201 throw exceptions instead of terminating the program (see
202 @RefSect{advanced.throw_on_failures__and__noexcept__,
204 (This is declared @c noexcept(false) since C++11.)
206 ~specify_except() BOOST_NOEXCEPT_IF(false) {}
209 Allow to specify exception guarantees.
211 @param f Nullary functor called by this library to check exception
213 Assertions within this functor are usually programmed using
214 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
215 call to this functor indicates a contract assertion failure (and
216 will result in this library calling
217 @RefFunc{boost::contract::except_failure}).
218 This functor should capture variables by (constant) references
219 (to access the values they will have at function exit).
221 @return After exception guarantees have been specified, the object returned
222 by this function does not allow to specify any additional contract.
225 specify_nothing except(F const& f) {
226 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
231 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_except,
232 boost::contract::detail::cond_base)
234 // Friends (used to limit library's public API).
238 template<typename VR>
239 friend class specify_precondition_old_postcondition_except;
241 template<typename VR>
242 friend class specify_old_postcondition_except;
244 template<typename VR>
245 friend class specify_postcondition_except;
250 Allow to specify postconditions or exception guarantees.
252 Allow to specify functors this library will call to check postconditions or
253 exception guarantees.
254 This object is internally constructed by this library when users specify
255 contracts calling @RefFunc{boost::contract::function} and similar functions
256 (that is why this class does not have a public constructor).
258 @see @RefSect{tutorial.postconditions, Postconditions},
259 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
261 @tparam VirtualResult Return type of the enclosing function declaring the
262 contract if that function is either a virtual public
263 function or a public function override.
264 Otherwise, this type is always @c void.
266 template<typename VirtualResult = void>
267 class specify_postcondition_except { // Privately copyable (as *).
270 Destruct this object.
272 @b Throws: This can throw in case programmers specify failure handlers that
273 throw exceptions instead of terminating the program (see
274 @RefSect{advanced.throw_on_failures__and__noexcept__,
276 (This is declared @c noexcept(false) since C++11.)
278 ~specify_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
281 Allow to specify postconditions.
283 @param f Functor called by this library to check postconditions
285 Assertions within this functor are usually programmed using
286 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
287 call to this functor indicates a contract assertion failure (and
288 will result in this library calling
289 @RefFunc{boost::contract::postcondition_failure}).
290 This functor should capture variables by (constant) references
291 (to access the values they will have at function exit).
292 This functor must be a nullary functor if @c VirtualResult is
293 @c void, otherwise it must be a unary functor accepting the
294 return value as a parameter of type <c>VirtualResult const&</c>
295 (to avoid extra copies of the return value, or of type
296 @c VirtualResult or <c>VirtualResult const</c> if extra copies
297 of the return value are irrelevant).
299 @return After postconditions have been specified, the object returned by
300 this function allows to optionally specify exception guarantees.
303 specify_except postcondition(F const& f) {
304 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
308 Allow to specify exception guarantees.
310 @param f Nullary functor called by this library to check exception
312 Assertions within this functor are usually programmed using
313 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
314 call to this functor indicates a contract assertion failure (and
315 will result in this library calling
316 @RefFunc{boost::contract::except_failure}).
317 This functor should capture variables by (constant) references
318 (to access the values they will have at function exit).
320 @return After exception guarantees have been specified, the object returned
321 by this function does not allow to specify any additional contract.
324 specify_nothing except(F const& f) {
325 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
330 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
331 specify_postcondition_except,
332 boost::contract::detail::cond_post<typename
333 boost::contract::detail::none_if_void<VirtualResult>::type>
336 // Friends (used to limit library's public API).
339 friend class specify_precondition_old_postcondition_except<VirtualResult>;
340 friend class specify_old_postcondition_except<VirtualResult>;
345 Allow to specify old value copies at body, postconditions, and exception
348 Allow to specify functors this library will call to copy old value at body,
349 check postconditions, and check exception guarantees.
350 This object is internally constructed by this library when users specify
351 contracts calling @RefFunc{boost::contract::function} and similar functions
352 (that is why this class does not have a public constructor).
354 @see @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
355 @RefSect{tutorial.postconditions, Postconditions},
356 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
358 @tparam VirtualResult Return type of the enclosing function declaring the
359 contract if that function is either a virtual public
360 function or a public function override.
361 Otherwise, this type is always @c void.
363 template<typename VirtualResult = void>
364 class specify_old_postcondition_except { // Privately copyable (as *).
367 Destruct this object.
369 @b Throws: This can throw in case programmers specify failure handlers that
370 throw exceptions instead of terminating the program (see
371 @RefSect{advanced.throw_on_failures__and__noexcept__,
373 (This is declared @c noexcept(false) since C++11.)
375 ~specify_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
378 Allow to specify old value copies at body.
380 It should often be sufficient to initialize old value pointers as soon as
381 they are declared, without using this function (see
382 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
384 @param f Nullary functor called by this library @c f() to assign old
385 value copies just before the body is executed but after entry
386 invariants (when they apply) and preconditions are checked.
387 Old value pointers within this functor call are usually assigned
388 using @RefMacro{BOOST_CONTRACT_OLDOF}.
389 Any exception thrown by a call to this functor will result in
390 this library calling @RefFunc{boost::contract::old_failure}
391 (because old values could not be copied to check postconditions
392 and exception guarantees).
393 This functor should capture old value pointers by references so
394 they can be assigned (all other variables needed to evaluate old
395 value expressions can be captured by (constant) value, or better
396 by (constant) reference to avoid extra copies).
398 @return After old value copies at body have been specified, the object
399 returned by this function allows to optionally specify
400 postconditions and exception guarantees.
403 specify_postcondition_except<VirtualResult> old(F const& f) {
404 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
408 Allow to specify postconditions.
410 @param f Functor called by this library to check postconditions
412 Assertions within this functor are usually programmed using
413 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
414 call to this functor indicates a contract assertion failure (and
415 will result in this library calling
416 @RefFunc{boost::contract::postcondition_failure}).
417 This functor should capture variables by (constant) references
418 (to access the values they will have at function exit).
419 This functor must be a nullary functor if @c VirtualResult is
420 @c void, otherwise it must be a unary functor accepting the
421 return value as a parameter of type <c>VirtualResult const&</c>
422 (to avoid extra copies of the return value, or of type
423 @c VirtualResult or <c>VirtualResult const</c> if extra copies
424 of the return value are irrelevant).
426 @return After postconditions have been specified, the object returned by
427 this function allows to optionally specify exception guarantees.
430 specify_except postcondition(F const& f) {
431 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
435 Allow to specify exception guarantees.
437 @param f Nullary functor called by this library to check exception
439 Assertions within this functor are usually programmed using
440 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
441 call to this functor indicates a contract assertion failure (and
442 will result in this library calling
443 @RefFunc{boost::contract::except_failure}).
444 This functor should capture variables by (constant) references
445 (to access the values they will have at function exit).
447 @return After exception guarantees have been specified, the object returned
448 by this function does not allow to specify any additional contract.
451 specify_nothing except(F const& f) {
452 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
457 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
458 specify_old_postcondition_except,
459 boost::contract::detail::cond_post<typename
460 boost::contract::detail::none_if_void<VirtualResult>::type>
463 // Friends (used to limit library's public API).
466 friend class specify_precondition_old_postcondition_except<VirtualResult>;
469 friend specify_old_postcondition_except<> constructor(C*);
472 friend specify_old_postcondition_except<> destructor(C*);
477 Allow to specify preconditions, old value copies at body, postconditions, and
478 exception guarantees.
480 Allow to specify functors this library will call to check preconditions, copy
481 old values at body, check postconditions, and check exception guarantees.
482 This object is internally constructed by this library when users specify
483 contracts calling @RefFunc{boost::contract::function} and similar functions
484 (that is why this class does not have a public constructor).
486 @see @RefSect{tutorial.preconditions, Preconditions},
487 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
488 @RefSect{tutorial.postconditions, Postconditions},
489 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
491 @tparam VirtualResult Return type of the enclosing function declaring the
492 contract if that function is either a virtual public
493 function or a public function override.
494 Otherwise, this type is always @c void.
497 typename VirtualResult /* = void (already in fwd decl from decl.hpp) */
498 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
502 class specify_precondition_old_postcondition_except { // Priv. copyable (as *).
505 Destruct this object.
507 @b Throws: This can throw in case programmers specify failure handlers that
508 throw exceptions instead of terminating the program (see
509 @RefSect{advanced.throw_on_failures__and__noexcept__,
511 (This is declared @c noexcept(false) since C++11.)
513 ~specify_precondition_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
516 Allow to specify preconditions.
518 @param f Nullary functor called by this library to check preconditions
520 Assertions within this functor are usually programmed using
521 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
522 call to this functor indicates a contract assertion failure (and
523 will result in this library calling
524 @RefFunc{boost::contract::precondition_failure}).
525 This functor should capture variables by (constant) value, or
526 better by (constant) reference (to avoid extra copies).
528 @return After preconditions have been specified, the object returned by this
529 function allows to optionally specify old value copies at body,
530 postconditions, and exception guarantees.
533 specify_old_postcondition_except<VirtualResult> precondition(F const& f) {
534 BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_
538 Allow to specify old value copies at body.
540 It should often be sufficient to initialize old value pointers as soon as
541 they are declared, without using this function (see
542 @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
544 @param f Nullary functor called by this library @c f() to assign old
545 value copies just before the body is executed but after entry
546 invariants (when they apply) and preconditions are checked.
547 Old value pointers within this functor call are usually assigned
548 using @RefMacro{BOOST_CONTRACT_OLDOF}.
549 Any exception thrown by a call to this functor will result in
550 this library calling @RefFunc{boost::contract::old_failure}
551 (because old values could not be copied to check postconditions
552 and exception guarantees).
553 This functor should capture old value pointers by references so
554 they can be assigned (all other variables needed to evaluate old
555 value expressions can be captured by (constant) value, or better
556 by (constant) reference to avoid extra copies).
558 @return After old value copies at body have been specified, the object
559 returned by this functions allows to optionally specify
560 postconditions and exception guarantees.
563 specify_postcondition_except<VirtualResult> old(F const& f) {
564 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
568 Allow to specify postconditions.
570 @param f Functor called by this library to check postconditions
572 Assertions within this functor are usually programmed using
573 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
574 call to this functor indicates a contract assertion failure (and
575 will result in this library calling
576 @RefFunc{boost::contract::postcondition_failure}).
577 This functor should capture variables by (constant) references
578 (to access the values they will have at function exit).
579 This functor must be a nullary functor if @c VirtualResult is
580 @c void, otherwise it must be a unary functor accepting the
581 return value as a parameter of type <c>VirtualResult const&</c>
582 (to avoid extra copies of the return value, or of type
583 @c VirtualResult or <c>VirtualResult const</c> if extra copies
584 of the return value are irrelevant).
586 @return After postconditions have been specified, the object returned by
587 this function allows to optionally specify exception guarantees.
590 specify_except postcondition(F const& f) {
591 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
595 Allow to specify exception guarantees.
597 @param f Nullary functor called by this library to check exception
599 Assertions within this functor are usually programmed using
600 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
601 call to this functor indicates a contract assertion failure (and
602 will result in this library calling
603 @RefFunc{boost::contract::except_failure}).
604 This functor should capture variables by (constant) references
605 (to access the values they will have at function exit).
607 @return After exception guarantees have been specified, the object returned
608 by this function does not allow to specify any additional contract.
611 specify_nothing except(F const& f) {
612 BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
617 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
618 specify_precondition_old_postcondition_except,
619 boost::contract::detail::cond_post<typename
620 boost::contract::detail::none_if_void<VirtualResult>::type>
623 // Friends (used to limit library's public API).
626 friend specify_precondition_old_postcondition_except<> function();
629 friend specify_precondition_old_postcondition_except<> public_function();
632 friend specify_precondition_old_postcondition_except<> public_function(C*);
635 friend specify_precondition_old_postcondition_except<> public_function(
638 template<typename VR, class C>
639 friend specify_precondition_old_postcondition_except<VR> public_function(
642 BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
643 O, VR, F, C, Args, v, r, f, obj, args)
649 #endif // #include guard