1
2 #ifndef BOOST_CONTRACT_CONSTRUCTOR_HPP_
3 #define BOOST_CONTRACT_CONSTRUCTOR_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 contracts for constructors.
12 */
13
14 #include <boost/contract/core/config.hpp>
15 #include <boost/contract/core/specify.hpp>
16 #include <boost/contract/core/access.hpp>
17 #include <boost/contract/core/constructor_precondition.hpp>
18 #if !defined(BOOST_CONTRACT_NO_CONSTRUCTORS) || \
19 !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
20 defined(BOOST_CONTRACT_STATIC_LINK)
21 #include <boost/contract/detail/operation/constructor.hpp>
22 #endif
23
24 namespace boost { namespace contract {
25
26 /**
27 Program contracts for constructors.
28
29 This is used to specify postconditions, exception guarantees, old value copies
30 at body, and check class invariants for constructors (see
31 @RefClass{boost::contract::constructor_precondition} to specify preconditions
32 for constructors):
33
34 @code
35 class u {
36 friend class boost::contract:access;
37
38 void invariant() const { // Optional (as for static and volatile).
39 BOOST_CONTRACT_ASSERT(...);
40 ...
41 }
42
43 public:
44 u(...) {
45 boost::contract::old_ptr<old_type> old_var;
46 boost::contract::check c = boost::contract::constructor(this)
47 // No `.precondition` (use `constructor_precondition` instead).
48 .old([&] { // Optional.
49 old_var = BOOST_CONTRACT_OLDOF(old_expr);
50 ...
51 })
52 .postcondition([&] { // Optional.
53 BOOST_CONTRACT_ASSERT(...);
54 ...
55 })
56 .except([&] { // Optional.
57 BOOST_CONTRACT_ASSERT(...);
58 ...
59 })
60 ;
61
62 ... // Constructor body.
63 }
64
65 ...
66 };
67 @endcode
68
69 For optimization, this can be omitted for constructors that do not have
70 postconditions and exception guarantees, within classes that have no invariants.
71
72 @see @RefSect{tutorial.constructors, Constructors}
73
74 @param obj The object @c this from the scope of the enclosing constructor
75 declaring the contract.
76 (Constructors check all class invariants, including static and
77 volatile invariants, see @RefSect{tutorial.class_invariants,
78 Class Invariants} and
79 @RefSect{extras.volatile_public_functions,
80 Volatile Public Functions}).
81
82 @tparam Class The type of the class containing the constructor declaring the
83 contract.
84 (Usually this template parameter is automatically deduced by C++
85 and it does not need to be explicitly specified by programmers.)
86
87 @return The result of this function must be assigned to a variable of type
88 @RefClass{boost::contract::check} declared explicitly (i.e., without
89 using C++11 @c auto declarations) and locally just before the code of
90 the constructor body (otherwise this library will generate a run-time
91 error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}).
92 */
93 template<class Class>
constructor(Class * obj)94 specify_old_postcondition_except<> constructor(Class* obj) {
95 // Must #if also on ..._PRECONDITIONS here because specify_... is generic.
96 #if !defined(BOOST_CONTRACT_NO_CONSTRUCTORS) || \
97 !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
98 defined(BOOST_CONTRACT_STATIC_LINK)
99 return specify_old_postcondition_except<>(
100 new boost::contract::detail::constructor<Class>(obj));
101 #else
102 return specify_old_postcondition_except<>();
103 #endif
104 }
105
106 } } // namespace
107
108 #endif // #include guard
109
110