diff options
Diffstat (limited to 'boost/contract/core/constructor_precondition.hpp')
-rw-r--r-- | boost/contract/core/constructor_precondition.hpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/boost/contract/core/constructor_precondition.hpp b/boost/contract/core/constructor_precondition.hpp new file mode 100644 index 0000000000..7a7fa753aa --- /dev/null +++ b/boost/contract/core/constructor_precondition.hpp @@ -0,0 +1,122 @@ + +#ifndef BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_HPP_ +#define BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_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 +Program preconditions for constructors. +*/ + +// IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes. +#include <boost/contract/core/config.hpp> +#ifndef BOOST_CONTRACT_NO_PRECONDITIONS + #include <boost/contract/core/exception.hpp> + #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION + #include <boost/contract/detail/checking.hpp> + #endif +#endif + +namespace boost { namespace contract { + +/** +Program preconditions for constructors. + +This class must be the very first base of the class declaring the +constructor for which preconditions are programmed (that way constructor +arguments can be checked by preconditions even before they are used to +initialize other base classes): + +@code + class u + #define BASES private boost::contract::constructor_precondition<u>, \ + public b + : BASES + { + ... + #undef BASES + + public: + explicit u(unsigned x) : + boost::contract::constructor_precondition<u>([&] { + BOOST_CONTRACT_ASSERT(x != 0); + ... + }), + b(1.0 / float(x)) + { + ... + } + + ... + }; +@endcode + +User-defined classes should inherit privately from this class (to not alter the +public interface of user-defined classes). +In addition, this class should never be declared as a virtual base (because +virtual bases are initialized only once across the entire inheritance hierarchy +preventing preconditions of other base classes from being checked). + +Unions cannot have base classes in C++ so this class can be used to declare a +local object within the constructor definition just before +@RefFunc{boost::contract::constructor} is used (see +@RefSect{extras.unions, Unions}). + +@see @RefSect{tutorial.constructors, Constructors} + +@tparam Class The class type of the constructor for which preconditions are + being programmed. +*/ +template<class Class> +class constructor_precondition { // Copyable (has no data). +public: + /** + Construct this object without specifying constructor preconditions. + + This is implicitly called for those constructors of the contracted class + that do not specify preconditions. + + @note Calling this default constructor should amount to negligible + compile-time and run-time overheads (likely to be optimized away + completely by most compilers). + */ + constructor_precondition() {} + + /** + Construct this object specifying constructor preconditions. + + @param f Nullary functor called by this library to check constructor + preconditions @c f(). + Assertions within this functor call are usually programmed + using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown + by a call to this functor indicates a contract failure (and will + result in this library calling + @RefFunc{boost::contract::precondition_failure}). + This functor should capture variables by (constant) value, or + better by (constant) reference to avoid extra copies. + */ + template<typename F> + explicit constructor_precondition(F const& f) { + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + try { + #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION + if(boost::contract::detail::checking::already()) return; + #ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION + boost::contract::detail::checking k; + #endif + #endif + f(); + } catch(...) { precondition_failure(from_constructor); } + #endif + } + + // Default copy operations (so user's derived classes can be copied, etc.). +}; + +} } // namespace + +#endif // #include guard + |