• 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.
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