• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Copyright (C) 2008-2018 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0 (see accompanying
4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
6 
7 // Test old values of non-copyable types (using macro interface).
8 
9 #include "if_copyable.hpp"
10 #include "../detail/unprotected_commas.hpp"
11 #include <boost/contract_macro.hpp>
12 #include <boost/noncopyable.hpp>
13 #include <boost/detail/lightweight_test.hpp>
14 
15 unsigned old_checks;
16 
17 template<typename T>
18 struct b {
nextb19     virtual void next(T& x, boost::contract::virtual_* v = 0) {
20         BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(
21             typename boost::contract::test::detail::unprotected_commas<T, void,
22                     void>::type1
23         )(
24             (boost::contract::test::detail::unprotected_commas<void, void,
25                     void>::same(v)),
26             old_x,
27             (boost::contract::test::detail::unprotected_commas<void, void,
28                     void>::same(x))
29         );
30         BOOST_CONTRACT_PUBLIC_FUNCTION(
31             boost::contract::test::detail::unprotected_commas<void, void,
32                     void>::same(v),
33             boost::contract::test::detail::unprotected_commas<void, void,
34                     void>::same(this)
35         )
36             BOOST_CONTRACT_POSTCONDITION([&] {
37                 boost::contract::test::detail::unprotected_commas<
38                         void, void, void>::call();
39                 if(old_x) {
40                     BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
41                     ++old_checks;
42                 }
43             })
44         ;
45         ++x;
46     }
47     BOOST_CONTRACT_OVERRIDE(next)
48 };
49 
50 template<typename T>
51 struct a
52     #define BASES public b<T>
53     : BASES
54 {
55     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
56     #undef BASES
57 
nexta58     virtual void next(T& x, boost::contract::virtual_* v = 0) /* override */ {
59         BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(
60             typename boost::contract::test::detail::unprotected_commas<T, void,
61                     void>::type1
62         )(
63             (boost::contract::test::detail::unprotected_commas<void, void,
64                     void>::same(v)),
65             old_x,
66             (boost::contract::test::detail::unprotected_commas<void, void,
67                     void>::same(x))
68         );
69         BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE(
70             typename boost::contract::test::detail::unprotected_commas<
71                     override_next, void, void>::type1
72         )(
73             boost::contract::test::detail::unprotected_commas<void, void,
74                     void>::same(v),
75             &a::next,
76             boost::contract::test::detail::unprotected_commas<void, void,
77                     void>::same(this),
78             boost::contract::test::detail::unprotected_commas<void, void,
79                     void>::same(x)
80         )
81             BOOST_CONTRACT_POSTCONDITION([&] {
82                 boost::contract::test::detail::unprotected_commas<
83                         void, void, void>::call();
84                 if(old_x) {
85                     BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
86                     ++old_checks;
87                 }
88             })
89         ;
90         ++x;
91     }
92     BOOST_CONTRACT_OVERRIDE(next)
93 };
94 
95 template<typename T>
next(T & x)96 void next(T& x) {
97     BOOST_CONTRACT_OLD_PTR_IF_COPYABLE(
98         typename boost::contract::test::detail::unprotected_commas<T, void,
99                 void>::type1
100     )(
101         old_x,
102         (boost::contract::test::detail::unprotected_commas<void, void,
103                 void>::same(x))
104     );
105     BOOST_CONTRACT_FUNCTION()
106         BOOST_CONTRACT_POSTCONDITION([&] {
107             boost::contract::test::detail::unprotected_commas<void, void, void>
108                     ::call();
109             if(old_x) {
110                 BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
111                 ++old_checks;
112             }
113         })
114     ;
115     ++x;
116 }
117 
main()118 int main() {
119     int i = 1; // Test built-in copyable type.
120     cp c(1); // Test custom copyable type.
121     ncp n(1); // Test non-copyable type.
122 
123     // Test free functions (old values without `v`).
124 
125     unsigned cnt =
126         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
127             1
128         #else
129             0
130         #endif
131     ;
132 
133     old_checks = 0;
134     next(i);
135     BOOST_TEST_EQ(old_checks, cnt);
136 
137     old_checks = 0;
138     next(c);
139     BOOST_TEST_EQ(old_checks, cnt);
140 
141     old_checks = 0;
142     next(n);
143     BOOST_TEST_EQ(old_checks, 0u);
144 
145     // Test virtual functions (old values with `v`).
146 
147     cnt =
148         #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
149             2
150         #else
151             0
152         #endif
153     ;
154 
155     a<int> ai;
156     old_checks = 0;
157     ai.next(i);
158     BOOST_TEST_EQ(old_checks, cnt);
159 
160     a<cp> ac;
161     old_checks = 0;
162     ac.next(c);
163     BOOST_TEST_EQ(old_checks, cnt);
164 
165     a<ncp> an;
166     old_checks = 0;
167     an.next(n);
168     BOOST_TEST_EQ(old_checks, 0u);
169 
170     return boost::report_errors();
171 }
172 
173