• 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 //[meyer97_stack4
8 // File: stack4.hpp
9 #ifndef STACK4_HPP_
10 #define STACK4_HPP_
11 
12 #include <boost/contract.hpp>
13 
14 // Dispenser with LIFO access policy and fixed max capacity.
15 template<typename T>
16 class stack4
17     #define BASES private boost::contract::constructor_precondition<stack4<T> >
18     : BASES
19 {
20     friend boost::contract::access;
21     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
22     #undef BASES
23 
invariant() const24     void invariant() const {
25         BOOST_CONTRACT_ASSERT(count() >= 0); // Count non-negative.
26         BOOST_CONTRACT_ASSERT(count() <= capacity()); // Count bounded.
27         BOOST_CONTRACT_ASSERT(empty() == (count() == 0)); // Empty if no elem.
28     }
29 
30 public:
31     /* Initialization */
32 
33     // Allocate static from a maximum of n elements.
stack4(int n)34     explicit stack4(int n) :
35         boost::contract::constructor_precondition<stack4>([&] {
36             BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative capacity.
37         })
38     {
39         boost::contract::check c = boost::contract::constructor(this)
__anone3f058ba0202null40             .postcondition([&] {
41                 BOOST_CONTRACT_ASSERT(capacity() == n); // Capacity set.
42             })
43         ;
44 
45         capacity_ = n;
46         count_ = 0;
47         array_ = new T[n];
48     }
49 
50     // Deep copy via constructor.
stack4(stack4 const & other)51     /* implicit */ stack4(stack4 const& other) {
52         boost::contract::check c = boost::contract::constructor(this)
53             .postcondition([&] {
54                 BOOST_CONTRACT_ASSERT(capacity() == other.capacity());
55                 BOOST_CONTRACT_ASSERT(count() == other.count());
56                 BOOST_CONTRACT_ASSERT_AXIOM(*this == other);
57             })
58         ;
59 
60         capacity_ = other.capacity_;
61         count_ = other.count_;
62         array_ = new T[other.capacity_];
63         for(int i = 0; i < other.count_; ++i) array_[i] = other.array_[i];
64     }
65 
66     // Deep copy via assignment.
operator =(stack4 const & other)67     stack4& operator=(stack4 const& other) {
68         boost::contract::check c = boost::contract::public_function(this)
69             .postcondition([&] {
70                 BOOST_CONTRACT_ASSERT(capacity() == other.capacity());
71                 BOOST_CONTRACT_ASSERT(count() == other.count());
72                 BOOST_CONTRACT_ASSERT_AXIOM(*this == other);
73             })
74         ;
75 
76         delete[] array_;
77         capacity_ = other.capacity_;
78         count_ = other.count_;
79         array_ = new T[other.capacity_];
80         for(int i = 0; i < other.count_; ++i) array_[i] = other.array_[i];
81         return *this;
82     }
83 
84     // Destroy this stack.
~stack4()85     virtual ~stack4() {
86         // Check invariants.
87         boost::contract::check c = boost::contract::destructor(this);
88         delete[] array_;
89     }
90 
91     /* Access */
92 
93     // Max number of stack elements.
capacity() const94     int capacity() const {
95         // Check invariants.
96         boost::contract::check c = boost::contract::public_function(this);
97         return capacity_;
98     }
99 
100     // Number of stack elements.
count() const101     int count() const {
102         // Check invariants.
103         boost::contract::check c = boost::contract::public_function(this);
104         return count_;
105     }
106 
107     // Top element.
item() const108     T const& item() const {
109         boost::contract::check c = boost::contract::public_function(this)
110             .precondition([&] {
111                 BOOST_CONTRACT_ASSERT(!empty()); // Not empty (i.e., count > 0).
112             })
113         ;
114 
115         return array_[count_ - 1];
116     }
117 
118     /* Status Report */
119 
120     // Is stack empty?
empty() const121     bool empty() const {
122         bool result;
123         boost::contract::check c = boost::contract::public_function(this)
124             .postcondition([&] {
125                 // Empty definition.
126                 BOOST_CONTRACT_ASSERT(result == (count() == 0));
127             })
128         ;
129 
130         return result = (count_ == 0);
131     }
132 
133     // Is stack full?
full() const134     bool full() const {
135         bool result;
136         boost::contract::check c = boost::contract::public_function(this)
137             .postcondition([&] {
138                 BOOST_CONTRACT_ASSERT( // Full definition.
139                         result == (count() == capacity()));
140             })
141         ;
142 
143         return result = (count_ == capacity_);
144     }
145 
146     /* Element Change */
147 
148     // Add x on top.
put(T const & x)149     void put(T const& x) {
150         boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count());
151         boost::contract::check c = boost::contract::public_function(this)
152             .precondition([&] {
153                 BOOST_CONTRACT_ASSERT(!full()); // Not full.
154             })
155             .postcondition([&] {
156                 BOOST_CONTRACT_ASSERT(!empty()); // Not empty.
157                 BOOST_CONTRACT_ASSERT(item() == x); // Added to top.
158                 BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // One more.
159             })
160         ;
161 
162         array_[count_++] = x;
163     }
164 
165     // Remove top element.
remove()166     void remove() {
167         boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count());
168         boost::contract::check c = boost::contract::public_function(this)
169             .precondition([&] {
170                 BOOST_CONTRACT_ASSERT(!empty()); // Not empty (i.e., count > 0).
171             })
172             .postcondition([&] {
173                 BOOST_CONTRACT_ASSERT(!full()); // Not full.
174                 BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // One less.
175             })
176         ;
177 
178         --count_;
179     }
180 
181     /* Friend Helpers */
182 
operator ==(stack4 const & left,stack4 const & right)183     friend bool operator==(stack4 const& left, stack4 const& right) {
184         boost::contract::check inv1 = boost::contract::public_function(&left);
185         boost::contract::check inv2 = boost::contract::public_function(&right);
186         if(left.count_ != right.count_) return false;
187         for(int i = 0; i < left.count_; ++i) {
188             if(left.array_[i] != right.array_[i]) return false;
189         }
190         return true;
191     }
192 
193 private:
194     int capacity_;
195     int count_;
196     T* array_; // Internally use C-style array.
197 };
198 
199 #endif // #include guard
200 //]
201 
202