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