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 values copied at body, postconditions, and exception
14 Preconditions, old values copied 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. Furthermore, on some C++98
46 // compilers, this private copy ctor gives a warning (because of lack of copy
47 // optimization on those compilers), this warning can be ignored.
48 #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
49 defined(BOOST_CONTRACT_STATIC_LINK)
50 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
52 boost::contract::detail::auto_ptr<cond_type > cond_; \
53 explicit class_type(cond_type* cond) : cond_(cond) {} \
54 class_type(class_type const& other) : cond_(other.cond_) {} \
55 class_type& operator=(class_type const& other) { \
56 cond_ = other.cond_; \
60 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ cond_.release()
62 #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
65 class_type(class_type const&) {} \
66 class_type& operator=(class_type const&) { return *this; }
68 #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ /* nothing */
71 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
72 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
73 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
75 return specify_old_postcondition_except<VirtualResult>( \
76 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
78 #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
79 return specify_old_postcondition_except<VirtualResult>( \
80 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
83 #ifndef BOOST_CONTRACT_NO_OLDS
84 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
85 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
87 return specify_postcondition_except<VirtualResult>( \
88 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
90 #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
91 return specify_postcondition_except<VirtualResult>( \
92 BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
95 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
96 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
97 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
99 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
101 #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
102 return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
105 #ifndef BOOST_CONTRACT_NO_EXCEPTS
106 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
107 BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
108 cond_->set_except(f); \
109 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
111 #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
112 return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
123 template<typename VR>
124 class specify_precondition_old_postcondition_except;
126 template<typename VR>
127 class specify_old_postcondition_except;
129 template<typename VR>
130 class specify_postcondition_except;
132 class specify_except;
136 namespace boost { namespace contract {
139 Used to prevent setting other contract conditions after exception guarantees.
141 This class has no member function so it is used to prevent specifying additional
142 functors to check any other contract.
143 This object is internally constructed by the library when users specify
144 contracts calling @RefFunc{boost::contract::function} and similar functions
145 (that is why this class does not have a public constructor).
147 @see @RefSect{tutorial, Tutorial}
149 class specify_nothing { // Privately copyable (as *).
152 Destruct this object.
154 @b Throws: This is declared @c noexcept(false) since C++11 to allow users
155 to program failure handlers that throw exceptions on contract
156 assertion failures (not the default, see
157 @RefSect{advanced.throw_on_failures__and__noexcept__,
160 ~specify_nothing() BOOST_NOEXCEPT_IF(false) {}
162 // No set member function here.
166 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_nothing,
167 boost::contract::detail::cond_base)
169 // Friends (used to limit library's public API).
173 template<typename VR>
174 friend class specify_precondition_old_postcondition_except;
176 template<typename VR>
177 friend class specify_old_postcondition_except;
179 template<typename VR>
180 friend class specify_postcondition_except;
182 friend class specify_except;
187 Allow to specify exception guarantees.
189 Allow to specify the functor this library will call to check exception
191 This object is internally constructed by the library when users specify
192 contracts calling @RefFunc{boost::contract::function} and similar functions
193 (that is why this class does not have a public constructor).
195 @see @RefSect{tutorial.exception_guarantees, Exception Guarantees}
197 class specify_except { // Privately copyable (as *).
200 Destruct this object.
202 @b Throws: This is declared @c noexcept(false) since C++11 to allow users
203 to program failure handlers that throw exceptions on contract
204 assertion failures (not the default, see
205 @RefSect{advanced.throw_on_failures__and__noexcept__,
208 ~specify_except() BOOST_NOEXCEPT_IF(false) {}
211 Allow to specify exception guarantees.
213 @param f Nullary functor called by this library to check exception
215 Assertions within this functor are usually programmed using
216 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
217 call to this functor indicates a contract assertion failure (and
218 will result in this library calling
219 @RefFunc{boost::contract::except_failure}).
220 This functor should capture variables by (constant) references
221 (to access the values they will have at function exit).
223 @return After exception guarantees have been specified, the object returned
224 by this function does not allow to specify any additional contract.
227 specify_nothing except(
229 #if !defined(BOOST_CONTRACT_NO_EXCEPTS) || \
230 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
232 #endif // Else, no name (avoid unused param warning).
233 ) { BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ }
237 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_except,
238 boost::contract::detail::cond_base)
240 // Friends (used to limit library's public API).
244 template<typename VR>
245 friend class specify_precondition_old_postcondition_except;
247 template<typename VR>
248 friend class specify_old_postcondition_except;
250 template<typename VR>
251 friend class specify_postcondition_except;
256 Allow to specify postconditions or exception guarantees.
258 Allow to specify functors this library will call to check postconditions or
259 exception guarantees.
260 This object is internally constructed by the library when users specify
261 contracts calling @RefFunc{boost::contract::function} and similar functions
262 (that is why this class does not have a public constructor).
264 @see @RefSect{tutorial.postconditions, Postconditions},
265 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
267 @tparam VirtualResult Return type of the enclosing function declaring the
268 contract if that is either a virtual or an
269 overriding public function, otherwise this is always
271 (Usually this template parameter is automatically
272 deduced by C++ and it does not need to be explicitly
273 specified by programmers.)
275 template<typename VirtualResult = void>
276 class specify_postcondition_except { // Privately copyable (as *).
279 Destruct this object.
281 @b Throws: This is declared @c noexcept(false) since C++11 to allow users
282 to program failure handlers that throw exceptions on contract
283 assertion failures (not the default, see
284 @RefSect{advanced.throw_on_failures__and__noexcept__,
287 ~specify_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
290 Allow to specify postconditions.
292 @param f Functor called by this library to check postconditions
293 @c f() or @c f(result).
294 Assertions within this functor are usually programmed using
295 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
296 call to this functor indicates a contract assertion failure (and
297 will result in this library calling
298 @RefFunc{boost::contract::postcondition_failure}).
299 This functor should capture variables by (constant) references
300 (to access the values they will have at function exit).
301 This functor must be a nullary functor @c f() if
302 @c VirtualResult is @c void, otherwise it must be a unary
303 functor @c f(result) accepting the return value @c result as a
304 parameter of type <c>VirtualResult const&</c> (to avoid extra
305 copies of the return value, or of type @c VirtualResult or
306 <c>VirtualResult const</c> if extra copies of the return value
309 @return After postconditions have been specified, the object returned by
310 this function allows to optionally specify exception guarantees.
313 specify_except postcondition(
315 #if !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
316 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
318 #endif // Else, no name (avoid unused param warning).
320 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
324 Allow to specify exception guarantees.
326 @param f Nullary functor called by this library to check exception
328 Assertions within this functor are usually programmed using
329 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
330 call to this functor indicates a contract assertion failure (and
331 will result in this library calling
332 @RefFunc{boost::contract::except_failure}).
333 This functor should capture variables by (constant) references
334 (to access the values they will have at function exit).
336 @return After exception guarantees have been specified, the object returned
337 by this function does not allow to specify any additional contract.
340 specify_nothing except(
342 #if !defined(BOOST_CONTRACT_NO_EXCEPTS) || \
343 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
345 #endif // Else, no name (avoid unused param warning).
346 ) { BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ }
350 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
351 specify_postcondition_except,
352 boost::contract::detail::cond_post<typename
353 boost::contract::detail::none_if_void<VirtualResult>::type>
356 // Friends (used to limit library's public API).
359 friend class specify_precondition_old_postcondition_except<VirtualResult>;
360 friend class specify_old_postcondition_except<VirtualResult>;
365 Allow to specify old values copied at body, postconditions, and exception
368 Allow to specify functors this library will call to copy old values at body,
369 check postconditions, and check exception guarantees.
370 This object is internally constructed by the library when users specify
371 contracts calling @RefFunc{boost::contract::function} and similar functions
372 (that is why this class does not have a public constructor).
374 @see @RefSect{advanced.old_values_copied_at_body, Old Values Copied at Body},
375 @RefSect{tutorial.postconditions, Postconditions},
376 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
378 @tparam VirtualResult Return type of the enclosing function declaring the
379 contract if that is either a virtual or an
380 overriding public function, otherwise this is always
382 (Usually this template parameter is automatically
383 deduced by C++ and it does not need to be explicitly
384 specified by programmers.)
386 template<typename VirtualResult = void>
387 class specify_old_postcondition_except { // Privately copyable (as *).
390 Destruct this object.
392 @b Throws: This is declared @c noexcept(false) since C++11 to allow users
393 to program failure handlers that throw exceptions on contract
394 assertion failures (not the default, see
395 @RefSect{advanced.throw_on_failures__and__noexcept__,
398 ~specify_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
401 Allow to specify old values copied at body.
403 It should often be sufficient to initialize old value pointers as soon as
404 they are declared, without using this function (see
405 @RefSect{advanced.old_values_copied_at_body, Old Values Copied at Body}).
407 @param f Nullary functor called by this library @c f() to assign old
408 value copies just before the body is executed but after entry
409 invariants (when they apply) and preconditions are checked.
410 Old value pointers within this functor call are usually assigned
411 using @RefMacro{BOOST_CONTRACT_OLDOF}.
412 Any exception thrown by a call to this functor will result in
413 this library calling @RefFunc{boost::contract::old_failure}
414 (because old values could not be copied to check postconditions
415 and exception guarantees).
416 This functor should capture old value pointers by references so
417 they can be assigned (all other variables needed to evaluate old
418 value expressions can be captured by (constant) value, or better
419 by (constant) reference to avoid extra copies).
421 @return After old values copied at body have been specified, the object
422 returned by this function allows to optionally specify
423 postconditions and exception guarantees.
426 specify_postcondition_except<VirtualResult> old(
428 #if !defined(BOOST_CONTRACT_NO_OLDS) || \
429 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
431 #endif // Else, no name (avoid unused param warning).
433 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
437 Allow to specify postconditions.
439 @param f Functor called by this library to check postconditions
440 @c f() or @c f(result).
441 Assertions within this functor are usually programmed using
442 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
443 call to this functor indicates a contract assertion failure (and
444 will result in this library calling
445 @RefFunc{boost::contract::postcondition_failure}).
446 This functor should capture variables by (constant) references
447 (to access the values they will have at function exit).
448 This functor must be a nullary functor @c f() if
449 @c VirtualResult is @c void, otherwise it must be a unary
450 functor @c f(result) accepting the return value @c result as a
451 parameter of type <c>VirtualResult const&</c> (to avoid extra
452 copies of the return value, or of type @c VirtualResult or
453 <c>VirtualResult const</c> if extra copies of the return value
456 @return After postconditions have been specified, the object returned by
457 this function allows to optionally specify exception guarantees.
460 specify_except postcondition(
462 #if !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
463 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
465 #endif // Else, no name (avoid unused param warning).
467 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
471 Allow to specify exception guarantees.
473 @param f Nullary functor called by this library to check exception
475 Assertions within this functor are usually programmed using
476 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
477 call to this functor indicates a contract assertion failure (and
478 will result in this library calling
479 @RefFunc{boost::contract::except_failure}).
480 This functor should capture variables by (constant) references
481 (to access the values they will have at function exit).
483 @return After exception guarantees have been specified, the object returned
484 by this function does not allow to specify any additional contract.
487 specify_nothing except(
489 #if !defined(BOOST_CONTRACT_NO_EXCEPTS) || \
490 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
492 #endif // Else, no name (avoid unused param warning).
493 ) { BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ }
497 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
498 specify_old_postcondition_except,
499 boost::contract::detail::cond_post<typename
500 boost::contract::detail::none_if_void<VirtualResult>::type>
503 // Friends (used to limit library's public API).
506 friend class specify_precondition_old_postcondition_except<VirtualResult>;
509 friend specify_old_postcondition_except<> constructor(C*);
512 friend specify_old_postcondition_except<> destructor(C*);
517 Allow to specify preconditions, old values copied at body, postconditions, and
518 exception guarantees.
520 Allow to specify functors this library will call to check preconditions, copy
521 old values at body, check postconditions, and check exception guarantees.
522 This object is internally constructed by the library when users specify
523 contracts calling @RefFunc{boost::contract::function} and similar functions
524 (that is why this class does not have a public constructor).
526 @see @RefSect{tutorial.preconditions, Preconditions},
527 @RefSect{advanced.old_values_copied_at_body, Old Values Copied at Body},
528 @RefSect{tutorial.postconditions, Postconditions},
529 @RefSect{tutorial.exception_guarantees, Exception Guarantees}
531 @tparam VirtualResult Return type of the enclosing function declaring the
532 contract if that is either a virtual or an
533 overriding public function, otherwise this is always
535 (Usually this template parameter is automatically
536 deduced by C++ and it does not need to be explicitly
537 specified by programmers.)
540 typename VirtualResult /* = void (already in fwd decl from decl.hpp) */
541 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
545 class specify_precondition_old_postcondition_except { // Priv. copyable (as *).
548 Destruct this object.
550 @b Throws: This is declared @c noexcept(false) since C++11 to allow users
551 to program failure handlers that throw exceptions on contract
552 assertion failures (not the default, see
553 @RefSect{advanced.throw_on_failures__and__noexcept__,
556 ~specify_precondition_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
559 Allow to specify preconditions.
561 @param f Nullary functor called by this library to check preconditions
563 Assertions within this functor are usually programmed using
564 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
565 call to this functor indicates a contract assertion failure (and
566 will result in this library calling
567 @RefFunc{boost::contract::precondition_failure}).
568 This functor should capture variables by (constant) value, or
569 better by (constant) reference (to avoid extra copies).
571 @return After preconditions have been specified, the object returned by this
572 function allows to optionally specify old values copied at body,
573 postconditions, and exception guarantees.
576 specify_old_postcondition_except<VirtualResult> precondition(
578 #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
579 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
581 #endif // Else, no name (avoid unused param warning).
583 BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_
587 Allow to specify old values copied at body.
589 It should often be sufficient to initialize old value pointers as soon as
590 they are declared, without using this function (see
591 @RefSect{advanced.old_values_copied_at_body, Old Values Copied at Body}).
593 @param f Nullary functor called by this library @c f() to assign old
594 value copies just before the body is executed but after entry
595 invariants (when they apply) and preconditions are checked.
596 Old value pointers within this functor call are usually assigned
597 using @RefMacro{BOOST_CONTRACT_OLDOF}.
598 Any exception thrown by a call to this functor will result in
599 this library calling @RefFunc{boost::contract::old_failure}
600 (because old values could not be copied to check postconditions
601 and exception guarantees).
602 This functor should capture old value pointers by references so
603 they can be assigned (all other variables needed to evaluate old
604 value expressions can be captured by (constant) value, or better
605 by (constant) reference to avoid extra copies).
607 @return After old values copied at body have been specified, the object
608 returned by this functions allows to optionally specify
609 postconditions and exception guarantees.
612 specify_postcondition_except<VirtualResult> old(
614 #if !defined(BOOST_CONTRACT_NO_OLDS) || \
615 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
617 #endif // Else, no name (avoid unused param warning).
619 BOOST_CONTRACT_SPECIFY_OLD_IMPL_
623 Allow to specify postconditions.
625 @param f Functor called by this library to check postconditions
626 @c f() or @c f(result).
627 Assertions within this functor are usually programmed using
628 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
629 call to this functor indicates a contract assertion failure (and
630 will result in this library calling
631 @RefFunc{boost::contract::postcondition_failure}).
632 This functor should capture variables by (constant) references
633 (to access the values they will have at function exit).
634 This functor must be a nullary functor @c f() if
635 @c VirtualResult is @c void, otherwise it must be a unary
636 functor @c f(result) accepting the return value @c result as a
637 parameter of type <c>VirtualResult const&</c> (to avoid extra
638 copies of the return value, or of type @c VirtualResult or
639 <c>VirtualResult const</c> if extra copies of the return value
642 @return After postconditions have been specified, the object returned by
643 this function allows to optionally specify exception guarantees.
646 specify_except postcondition(
648 #if !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
649 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
651 #endif // Else, no name (avoid unused param warning).
653 BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
657 Allow to specify exception guarantees.
659 @param f Nullary functor called by this library to check exception
661 Assertions within this functor are usually programmed using
662 @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
663 call to this functor indicates a contract assertion failure (and
664 will result in this library calling
665 @RefFunc{boost::contract::except_failure}).
666 This functor should capture variables by (constant) references
667 (to access the values they will have at function exit).
669 @return After exception guarantees have been specified, the object returned
670 by this function does not allow to specify any additional contract.
673 specify_nothing except(
675 #if !defined(BOOST_CONTRACT_NO_EXCEPTS) || \
676 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
678 #endif // Else, no name (avoid unused param warning).
679 ) { BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ }
683 BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
684 specify_precondition_old_postcondition_except,
685 boost::contract::detail::cond_post<typename
686 boost::contract::detail::none_if_void<VirtualResult>::type>
689 // Friends (used to limit library's public API).
692 friend specify_precondition_old_postcondition_except<> function();
695 friend specify_precondition_old_postcondition_except<> public_function();
698 friend specify_precondition_old_postcondition_except<> public_function(C*);
701 friend specify_precondition_old_postcondition_except<> public_function(
704 template<typename VR, class C>
705 friend specify_precondition_old_postcondition_except<VR> public_function(
708 BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
709 O, VR, F, C, Args, v, r, f, obj, args)
715 #endif // #include guard