• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #ifndef BOOST_CONTRACT_VIRTUAL_HPP_
3 #define BOOST_CONTRACT_VIRTUAL_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 Handle virtual public functions with contracts (for subcontracting).
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_CONDITIONS
17     #include <boost/contract/detail/decl.hpp>
18 #endif
19 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
20     #include <boost/any.hpp>
21 #endif
22 #ifndef BOOST_CONTRACT_NO_OLDS
23     #include <boost/shared_ptr.hpp>
24     #include <queue>
25 #endif
26 
27 namespace boost { namespace contract {
28 
29 #ifndef BOOST_CONTRACT_NO_CONDITIONS
30     namespace detail {
31         BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
32                 /* is_friend = */ 0, OO, RR, FF, CC, AArgs);
33     }
34 #endif
35 
36 /**
37 Type of extra function parameter to handle contracts for virtual public
38 functions (for subcontracting).
39 
40 Virtual public functions (and therefore also public function overrides)
41 declaring contracts using this library must specify an extra function parameter
42 at the very end of their parameter list.
43 This parameter must be a pointer to this class and it must have default value
44 @c 0 or @c nullptr (this extra parameter is often named @c v in this
45 documentation, but any name can be used):
46 
47 @code
48 class u {
49 public:
50     virtual void f(int x, boost::contract::virtual_* v = 0) { // Declare `v`.
51         ... // Contract declaration (which will use `v`) and function body.
52     }
53 
54     ...
55 };
56 @endcode
57 
58 In practice this extra parameter does not alter the calling interface of the
59 enclosing function declaring the contract because it is always the very last
60 parameter and it has a default value (so it can always be omitted when users
61 call the function).
62 This extra parameter must be passed to
63 @RefFunc{boost::contract::public_function}, @RefMacro{BOOST_CONTRACT_OLDOF}, and
64 all other operations of this library that accept a pointer to
65 @RefClass{boost::contract::virtual_}.
66 A part from that, this class is not intended to be directly used by programmers
67 (and that is why this class does not have any public member and it is not
68 copyable).
69 
70 @see    @RefSect{tutorial.virtual_public_functions, Virtual Public Functions},
71         @RefSect{tutorial.public_function_overrides__subcontracting_,
72         Public Function Overrides}
73 */
74 class virtual_ { // Non-copyable (see below) to avoid copy queue, stack, etc.
75 /** @cond */
76 private: // No public API (so users cannot use it directly by mistake).
77 
78     // No boost::noncopyable to avoid its overhead when contracts disabled.
79     virtual_(virtual_&);
80     virtual_& operator=(virtual_&);
81 
82     #ifndef BOOST_CONTRACT_NO_CONDITIONS
83         enum action_enum {
84             // virtual_ always held/passed as ptr so nullptr used for user call.
85             no_action,
86             #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
87                 check_entry_inv,
88             #endif
89             #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
90                 check_pre,
91             #endif
92             #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
93                 check_exit_inv,
94             #endif
95             #ifndef BOOST_CONTRACT_NO_OLDS
96                 // For outside .old(...).
97                 push_old_init_copy,
98                 // pop_old_init_copy as static function below.
99                 // For inside .old(...).
100                 call_old_ftor,
101                 push_old_ftor_copy,
102                 pop_old_ftor_copy,
103             #endif
104             #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
105                 check_post,
106             #endif
107             #ifndef BOOST_CONTRACT_NO_EXCEPTS
108                 check_except,
109             #endif
110         };
111     #endif
112 
113     #ifndef BOOST_CONTRACT_NO_OLDS
114         // Not just an enum value because the logical combination of two values.
pop_old_init_copy(action_enum a)115         inline static bool pop_old_init_copy(action_enum a) {
116             return
117                 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
118                     a == check_post
119                 #endif
120                 #if     !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) && \
121                         !defined(BOOST_CONTRACT_NO_EXCEPTS)
122                     ||
123                 #endif
124                 #ifndef BOOST_CONTRACT_NO_EXCEPTS
125                     a == check_except
126                 #endif
127             ;
128         }
129     #endif
130 
131     #ifndef BOOST_CONTRACT_NO_CONDITIONS
virtual_(action_enum a)132         explicit virtual_(action_enum a) :
133               action_(a)
134             , failed_(false)
135             #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
136                 , result_type_name_()
137                 , result_optional_()
138             #endif
139         {}
140     #endif
141 
142     #ifndef BOOST_CONTRACT_NO_CONDITIONS
143         action_enum action_;
144         bool failed_;
145     #endif
146     #ifndef BOOST_CONTRACT_NO_OLDS
147         std::queue<boost::shared_ptr<void> > old_init_copies_;
148         std::queue<boost::shared_ptr<void> > old_ftor_copies_;
149     #endif
150     #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
151         boost::any result_ptr_; // Result for virtual and overriding functions.
152         char const* result_type_name_;
153         bool result_optional_;
154     #endif
155 
156     // Friends (used to limit library's public API).
157     #ifndef BOOST_CONTRACT_NO_OLDS
158         friend bool copy_old(virtual_*);
159         friend class old_pointer;
160     #endif
161     #ifndef BOOST_CONTRACT_NO_CONDITIONS
162         BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
163                 /* is_friend = */ 1, OO, RR, FF, CC, AArgs);
164     #endif
165 /** @endcond */
166 };
167 
168 } } // namespace
169 
170 #endif // #include guard
171 
172