diff options
Diffstat (limited to 'boost/contract/check.hpp')
-rw-r--r-- | boost/contract/check.hpp | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/boost/contract/check.hpp b/boost/contract/check.hpp new file mode 100644 index 0000000000..e7423ce9a8 --- /dev/null +++ b/boost/contract/check.hpp @@ -0,0 +1,347 @@ + +#ifndef BOOST_CONTRACT_CHECK_HPP_ +#define BOOST_CONTRACT_CHECK_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +/** @file +RAII object that checks contracts. +*/ + +#include <boost/contract/core/config.hpp> +#include <boost/contract/core/check_macro.hpp> +#include <boost/contract/core/specify.hpp> +#include <boost/contract/core/exception.hpp> // For set_... (if always in code). +#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \ + defined(BOOST_CONTRACT_STATIC_LINK) + #include <boost/contract/detail/condition/cond_base.hpp> + #include <boost/contract/detail/auto_ptr.hpp> + #include <boost/contract/detail/debug.hpp> +#endif +#include <boost/contract/detail/check.hpp> +#include <boost/config.hpp> + +/* PRIVATE */ + +/** @cond */ + +#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \ + defined(BOOST_CONTRACT_STATIC_LINK) + #define BOOST_CONTRACT_CHECK_CTOR_DEF_(contract_type) \ + : cond_(const_cast<contract_type&>(contract).cond_.release()) \ + { \ + BOOST_CONTRACT_DETAIL_DEBUG(cond_); \ + cond_->initialize(); \ + } +#else + #define BOOST_CONTRACT_CHECK_CTOR_DEF_(contract_type) {} +#endif + +/** @endcond */ + +/* CODE */ + +namespace boost { namespace contract { + +/** +RAII object that checks the contracts. + +In general, when this object is constructed it checks class invariants at entry, +preconditions, and makes old value copies at body. +When it is destructed, it checks class invariants at exist, postconditions, and +exception guarantees. +This object enforces the following (see +@RefSect{contract_programming_overview, Contract Programming Overview}): + +@li Postconditions are checked only if the body does not throw an exception. +@li Exceptions guarantees are checked only if the body throws an exception. +@li Constructor entry never checks class invariants. +@li Destructor exit checks class invariants only if the body throws an +exception (even if destructors should usually not be programmed to throw +exceptions in C++). +@li Static invariants are always checked at entry and exit (and regardless of +the body throwing exceptions or not). + +When used this way, this object is usually constructed and initialized to the +return value of one of the contract functions +@RefFunc{boost::contract::function}, @RefFunc{boost::contract::constructor}, +@RefFunc{boost::contract::destructor}, or +@RefFunc{boost::contract::public_function}. +In addition, this object can be constructed from a nullary functor that is used +to program implementation checks. + +@see @RefSect{tutorial, Tutorial}, + @RefSect{advanced.implementation_checks, Implementation Checks} +*/ +class check { // Copy ctor only (as move via ptr release). +public: + // NOTE: Unfortunately, Apple compilers define a `check(...)` macro that + // clashes with the name of this class. In the following code, + // BOOST_PREVENT_MACRO_SUBSTITUTION is used to workaround these name + // clashes. In user code, `check c = ...` syntax is typically used also + // avoiding clashes. + + /** + Construct this object for implementation checks. + + This can be used to program checks within implementation code (body, etc.). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param f Nullary functor that asserts implementation checks. @c f() will + be called as soon as this object is constructed at the point it + is declared within the implementation code (see + @RefSect{advanced.implementation_checks, + Implementation Checks}). + */ + template<typename F> // Cannot check `if(f) ...` as f can be a lambda. + // f must be a valid callable object (not null func ptr, empty ftor, etc. + /* implicit */ check + /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + F const& f) { + BOOST_CONTRACT_DETAIL_CHECK({ f(); }) + } + + /** + Construct this object copying it from the specified one. + + This object will check the contract, the copied-from object will not (i.e., + contract check ownership is transferred from the copied object to the new + object being created by this constructor). + + @param other Copied-from object. + */ + check /** @cond **/ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + check const& other) + #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \ + defined(BOOST_CONTRACT_STATIC_LINK) + // Copy ctor moves cond_ pointer to dest. + : cond_(const_cast<check&>(other).cond_.release()) + #endif + {} + + /** + Construct this object to check the specified contract. + + This checks class invariants at entry (if those apply to the specified + contract). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param contract Contract to be checked (usually the return value of + @RefFunc{boost::contract::function} or + @RefFunc{boost::contract::public_function}). + + @tparam VirtualResult Return type of the enclosing function declaring the + contract if that is either a virtual or an + overriding public function. + Otherwise, this is always @c void. + */ + template<typename VirtualResult> + /* implicit */ check + /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + specify_precondition_old_postcondition_except<VirtualResult> const& + contract + ) + #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN + BOOST_CONTRACT_CHECK_CTOR_DEF_( + specify_precondition_old_postcondition_except<VirtualResult>) + #else + ; + #endif + + /** + Construct this object to check the specified contract. + + This checks class invariants at entry and preconditions (if any of those + apply to the specified contract). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param contract Contract to be checked (usually the return value of + @RefFunc{boost::contract::function}, + @RefFunc{boost::contract::constructor}, + @RefFunc{boost::contract::destructor}, or + @RefFunc{boost::contract::public_function}). + + @tparam VirtualResult Return type of the enclosing function declaring the + contract if that is either a virtual or an + overriding public function. + Otherwise, this is always @c void. + */ + template<typename VirtualResult> + /* implicit */ check + /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + specify_old_postcondition_except<VirtualResult> const& contract) + #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN + BOOST_CONTRACT_CHECK_CTOR_DEF_( + specify_old_postcondition_except<VirtualResult>) + #else + ; + #endif + + /** + Construct this object to check the specified contract. + + This checks class invariants at entry and preconditions then it makes old + value copies at body (if any of those apply to the specified contract). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating te + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param contract Contract to be checked (usually the return value of + @RefFunc{boost::contract::function}, + @RefFunc{boost::contract::constructor}, + @RefFunc{boost::contract::destructor}, or + @RefFunc{boost::contract::public_function}). + + @tparam VirtualResult Return type of the enclosing function declaring the + contract if that is either a virtual or an + overriding public function. + Otherwise, this is always @c void. + */ + template<typename VirtualResult> + /* implicit */ check + /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + specify_postcondition_except<VirtualResult> const& contract) + #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN + BOOST_CONTRACT_CHECK_CTOR_DEF_( + specify_postcondition_except<VirtualResult>) + #else + ; + #endif + + /** + Construct this object to check the specified contract. + + This checks class invariants at entry and preconditions then it makes old + value copies at body, plus the destructor of this object will check + postconditions in this case (if any of those apply to the specified + contract). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param contract Contract to be checked (usually the return value of + @RefFunc{boost::contract::function}, + @RefFunc{boost::contract::constructor}, + @RefFunc{boost::contract::destructor}, or + @RefFunc{boost::contract::public_function}). + + @tparam VirtualResult Return type of the enclosing function declaring the + contract if that is either a virtual or an + overriding public function. + Otherwise, this is always @c void. + */ + /* implicit */ check + /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + specify_except const& contract) + #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN + BOOST_CONTRACT_CHECK_CTOR_DEF_(specify_except) + #else + ; + #endif + + /** + Construct this object to check the specified contract. + + This checks class invariants at entry and preconditions then it makes old + value copies at body, plus the destructor of this object will check + postconditions and exception guarantees in this case (if any of those apply + to the specified contract). + This constructor is not declared @c explicit so initializations can use + assignment syntax @c =. + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + + @param contract Contract to be checked (usually the return value of + @RefFunc{boost::contract::function}, + @RefFunc{boost::contract::constructor}, + @RefFunc{boost::contract::destructor}, or + @RefFunc{boost::contract::public_function}). + + @tparam VirtualResult Return type of the enclosing function declaring the + contract if that is either a virtual or an + overriding public function. + Otherwise, this is always @c void. + */ + /* implicit */ check + /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ ( + specify_nothing const& contract) + #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN + BOOST_CONTRACT_CHECK_CTOR_DEF_(specify_nothing) + #else + ; + #endif + + /** + Destruct this object. + + This checks class invariants at exit and either postconditions when the + enclosing function body did not throw an exception, or exception guarantees + when the function body threw an exception (that is if class invariants, + postconditions, and exception guarantees respectively apply to the contract + parameter specified when constructing this object). + + @b Throws: This can throw in case programmers specify contract failure + handlers that throw exceptions instead of terminating the + program (see + @RefSect{advanced.throw_on_failures__and__noexcept__, + Throw on Failure}). + (This is declared @c noexcept(false) since C++11.) + */ + ~check /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () + BOOST_NOEXCEPT_IF(false) /* allow auto_ptr dtor to throw */ + {} + +/** @cond */ +private: + check& operator=(check const&); // Cannot copy outside of `check c = ...`. + + #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \ + defined(BOOST_CONTRACT_STATIC_LINK) + boost::contract::detail::auto_ptr<boost::contract::detail::cond_base> + cond_; + #endif +/** @endcond */ +}; + +} } // namespace + +#endif // #include guard + |