123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #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
- {
- friend class boost::contract::access;
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #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).
- This class cannot be used this way in a @c union because unions cannot have base
- classes in C++.
- Instead, this class is used in a @c union 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 The implementation of this library is optimized so that 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
|