1 2 #ifndef BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_HPP_ 3 #define BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_HPP_ 4 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 9 10 /** @file 11 Program preconditions for constructors. 12 */ 13 14 // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes. 15 #include <boost/contract/core/config.hpp> 16 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 17 #include <boost/contract/core/exception.hpp> 18 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION 19 #include <boost/contract/detail/checking.hpp> 20 #endif 21 #endif 22 23 namespace boost { namespace contract { 24 25 /** 26 Program preconditions for constructors. 27 28 This class must be the very first base of the class declaring the 29 constructor for which preconditions are programmed (that way constructor 30 arguments can be checked by preconditions even before they are used to 31 initialize other base classes): 32 33 @code 34 class u 35 #define BASES private boost::contract::constructor_precondition<u>, \ 36 public b 37 : BASES 38 { 39 friend class boost::contract::access; 40 41 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 42 #undef BASES 43 44 public: 45 explicit u(unsigned x) : 46 boost::contract::constructor_precondition<u>([&] { 47 BOOST_CONTRACT_ASSERT(x != 0); 48 ... 49 }), 50 b(1.0 / float(x)) 51 { 52 ... 53 } 54 55 ... 56 }; 57 @endcode 58 59 User-defined classes should inherit privately from this class (to not alter the 60 public interface of user-defined classes). 61 In addition, this class should never be declared as a virtual base (because 62 virtual bases are initialized only once across the entire inheritance hierarchy 63 preventing preconditions of other base classes from being checked). 64 65 This class cannot be used this way in a @c union because unions cannot have base 66 classes in C++. 67 Instead, this class is used in a @c union to declare a local object within the 68 constructor definition just before @RefFunc{boost::contract::constructor} is 69 used (see @RefSect{extras.unions, Unions}). 70 71 @see @RefSect{tutorial.constructors, Constructors} 72 73 @tparam Class The class type of the constructor for which preconditions are 74 being programmed. 75 */ 76 template<class Class> 77 class constructor_precondition { // Copyable (has no data). 78 public: 79 /** 80 Construct this object without specifying constructor preconditions. 81 82 This is implicitly called for those constructors of the contracted class 83 that do not specify preconditions. 84 85 @note The implementation of this library is optimized so that calling this 86 default constructor should amount to negligible compile-time and 87 run-time overheads (likely to be optimized away completely by most 88 compilers). 89 */ constructor_precondition()90 constructor_precondition() {} 91 92 /** 93 Construct this object specifying constructor preconditions. 94 95 @param f Nullary functor called by this library to check constructor 96 preconditions @c f(). 97 Assertions within this functor call are usually programmed 98 using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown 99 by a call to this functor indicates a contract failure (and will 100 result in this library calling 101 @RefFunc{boost::contract::precondition_failure}). 102 This functor should capture variables by (constant) value, or 103 better by (constant) reference to avoid extra copies. 104 */ 105 template<typename F> constructor_precondition(F const & f)106 explicit constructor_precondition(F const& f) { 107 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 108 try { 109 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION 110 if(boost::contract::detail::checking::already()) return; 111 #ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION 112 boost::contract::detail::checking k; 113 #endif 114 #endif 115 f(); 116 } catch(...) { precondition_failure(from_constructor); } 117 #endif 118 } 119 120 // Default copy operations (so user's derived classes can be copied, etc.). 121 }; 122 123 } } // namespace 124 125 #endif // #include guard 126 127