• 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 #include <boost/contract.hpp>
8 #include <boost/type_traits.hpp>
9 #include <boost/noncopyable.hpp>
10 #include <cassert>
11 
12 //[old_if_copyable_offset
13 template<typename T> // T might or might not be copyable.
offset(T & x,int count)14 void offset(T& x, int count) {
15     // No compiler error if T has no copy constructor...
16     boost::contract::old_ptr_if_copyable<T> old_x = BOOST_CONTRACT_OLDOF(x);
17     boost::contract::check c = boost::contract::function()
18         .postcondition([&] {
19             // ...but old value null if T has no copy constructor.
20             if(old_x) BOOST_CONTRACT_ASSERT(x == *old_x + count);
21         })
22     ;
23 
24     x += count;
25 }
26 //]
27 
28 //[old_if_copyable_w_decl
29 // Copyable type but...
30 class w {
31 public:
w(w const &)32     w(w const&) { /* Some very expensive copy operation here... */ }
33 
34     /* ... */
35 //]
w()36     w() : num_(0) {}
operator +(int i) const37     int operator+(int i) const { return num_ + i; }
operator +=(int i)38     w& operator+=(int i) { num_ += i; return *this; }
operator ==(int i) const39     bool operator==(int i) const { return long(num_) == i; }
40 private:
41     unsigned long num_;
42 };
43 
44 //[old_if_copyable_w_spec
45 // ...never copy old values for type `w` (because its copy is too expensive).
46 namespace boost { namespace contract {
47     template<>
48     struct is_old_value_copyable<w> : boost::false_type {};
49 } }
50 //]
51 
52 //[old_if_copyable_p_decl
53 // Non-copyable type but...
54 class p : private boost::noncopyable {
55     int* num_;
56 
57     friend struct boost::contract::old_value_copy<p>;
58 
59     /* ... */
60 //]
61 public:
p()62     p() : num_(new int(0)) {}
~p()63     ~p() { delete num_; }
operator +(int i) const64     int operator+(int i) const { return *num_ + i; }
operator +=(int i)65     p& operator+=(int i) { *num_ += i; return *this; }
operator ==(int i) const66     bool operator==(int i) const { return *num_ == i; }
67 };
68 
69 //[old_if_copyable_p_spec
70 // ...still copy old values for type `p` (using a deep copy).
71 namespace boost { namespace contract {
72     template<>
73     struct old_value_copy<p> {
old_value_copyboost::contract::old_value_copy74         explicit old_value_copy(p const& old) {
75             *old_.num_ = *old.num_; // Deep copy pointed value.
76         }
77 
oldboost::contract::old_value_copy78         p const& old() const { return old_; }
79 
80     private:
81         p old_;
82     };
83 
84     template<>
85     struct is_old_value_copyable<p> : boost::true_type {};
86 } }
87 //]
88 
89 //[old_if_copyable_n_decl
90 class n { // Do not want to use boost::noncopyable but...
91     int num_;
92 
93 private:
94     n(n const&); // ...unimplemented private copy constructor (so non-copyable).
95 
96     /* ... */
97 //]
98 
99 public:
n()100     n() : num_(0) {}
operator +(int i) const101     int operator+(int i) const { return num_ + i; }
operator +=(int i)102     n& operator+=(int i) { num_ += i; return *this; }
operator ==(int i) const103     bool operator==(int i) const { return num_ == i; }
104 };
105 
106 //[old_if_copyable_n_spec
107 // Specialize `boost::is_copy_constructible` (no need for this on C++11).
108 namespace boost { namespace contract {
109     template<>
110     struct is_old_value_copyable<n> : boost::false_type {};
111 } }
112 //]
113 
main()114 int main() {
115     int i = 0; // Copy constructor, copy and check old values.
116     offset(i, 3);
117     assert(i == 3);
118 
119     w j; // Expensive copy constructor, so never copy or check old values.
120     offset(j, 3);
121     assert(j == 3);
122 
123     p k; // No copy constructor, but still copy and check old values.
124     offset(k, 3);
125     assert(k == 3);
126 
127     n h; // No copy constructor, no compiler error but no old value checks.
128     offset(h, 3);
129     assert(h == 3);
130 
131     return 0;
132 }
133 
134