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.
8
9 #include "if_copyable.hpp"
10 #include <boost/contract/public_function.hpp>
11 #include <boost/contract/function.hpp>
12 #include <boost/contract/base_types.hpp>
13 #include <boost/contract/override.hpp>
14 #include <boost/contract/old.hpp>
15 #include <boost/contract/check.hpp>
16 #include <boost/contract/assert.hpp>
17 #include <boost/noncopyable.hpp>
18 #include <boost/detail/lightweight_test.hpp>
19
20 unsigned old_checks;
21
22 template<typename T>
23 struct b {
nextb24 virtual void next(T& x, boost::contract::virtual_* v = 0) {
25 boost::contract::old_ptr_if_copyable<T> old_x =
26 BOOST_CONTRACT_OLDOF(v, x);
27 boost::contract::check c = boost::contract::public_function(v, this)
28 .postcondition([&] {
29 if(old_x) {
30 BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
31 ++old_checks;
32 }
33 })
34 ;
35 ++x;
36 }
37 BOOST_CONTRACT_OVERRIDE(next)
38 };
39
40 template<typename T>
41 struct a
42 #define BASES public b<T>
43 : BASES
44 {
45 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
46 #undef BASES
47
nexta48 virtual void next(T& x, boost::contract::virtual_* v = 0) /* override */ {
49 boost::contract::old_ptr_if_copyable<T> old_x =
50 BOOST_CONTRACT_OLDOF(v, x);
51 boost::contract::check c = boost::contract::public_function<
52 override_next>(v, &a::next, this, x)
53 .postcondition([&] {
54 if(old_x) {
55 BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
56 ++old_checks;
57 }
58 })
59 ;
60 ++x;
61 }
62 BOOST_CONTRACT_OVERRIDE(next)
63 };
64
65 template<typename T>
next(T & x)66 void next(T& x) {
67 boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x);
68 boost::contract::check c = boost::contract::function()
69 .postcondition([&] {
70 if(old_x) {
71 BOOST_CONTRACT_ASSERT(x == *old_x + T(1));
72 ++old_checks;
73 }
74 })
75 ;
76 ++x;
77 }
78
main()79 int main() {
80 int i = 1; // Test built-in copyable type.
81 cp c(1); // Test custom copyable type.
82 ncp n(1); // Test non-copyable type.
83
84 // Test free functions (old values without `v`).
85
86 unsigned cnt =
87 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
88 1
89 #else
90 0
91 #endif
92 ;
93
94 old_checks = 0;
95 next(i);
96 BOOST_TEST_EQ(old_checks, cnt);
97
98 old_checks = 0;
99 next(c);
100 BOOST_TEST_EQ(old_checks, cnt);
101
102 old_checks = 0;
103 next(n);
104 BOOST_TEST_EQ(old_checks, 0u);
105
106 // Test virtual functions (old values with `v`).
107
108 cnt =
109 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
110 2
111 #else
112 0
113 #endif
114 ;
115
116 a<int> ai;
117 old_checks = 0;
118 ai.next(i);
119 BOOST_TEST_EQ(old_checks, cnt);
120
121 a<cp> ac;
122 old_checks = 0;
123 ac.next(c);
124 BOOST_TEST_EQ(old_checks, cnt);
125
126 a<ncp> an;
127 old_checks = 0;
128 an.next(n);
129 BOOST_TEST_EQ(old_checks, 0u);
130
131 return boost::report_errors();
132 }
133
134