]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 | { | |
92f5a8d4 TL |
39 | friend class boost::contract::access; |
40 | ||
41 | typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; | |
11fdf7f2 TL |
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 | ||
92f5a8d4 TL |
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}). | |
11fdf7f2 TL |
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 | ||
92f5a8d4 TL |
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). | |
11fdf7f2 TL |
89 | */ |
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> | |
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 |