Mercurial > Algorithms__Sedgewick
comparison algs4-c++/src/Queue.hpp @ 25:3cdac4c29445
Refactored Queue's iterator and const_iterator into a template.
The generic_iterator can be instatiated as either a const or non-const iterator
as needed. It uses <type_traits> std::conditional<>::type create the
appropriate types as needed.
I learned this trick here:
http://www.sj-vs.net/c-implementing-const_iterator-and-non-const-iterator-without-code-duplication/
author | Eris Caffee <discordia@eldalin.com> |
---|---|
date | Tue, 23 Jun 2015 15:27:26 -0500 |
parents | 028689700a47 |
children | 2cbfacd2a3e9 |
comparison
equal
deleted
inserted
replaced
4:be6ea53dbdfa | 5:89f5673d1606 |
---|---|
4 #define QUEUE_HPP | 4 #define QUEUE_HPP |
5 | 5 |
6 #include <cstddef> | 6 #include <cstddef> |
7 #include <cassert> | 7 #include <cassert> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <type_traits> | |
9 | 10 |
10 template <typename T> | 11 template <typename T> |
11 class Queue { | 12 class Queue { |
12 | 13 |
13 private: | 14 private: |
20 }; | 21 }; |
21 | 22 |
22 public: | 23 public: |
23 | 24 |
24 //////////////////////////////////// | 25 //////////////////////////////////// |
25 class iterator : public std::iterator<std::forward_iterator_tag, T> { | 26 |
27 template <bool is_const = true> | |
28 class generic_iterator : public std::iterator<std::forward_iterator_tag, T> { | |
29 | |
30 private: | |
31 typedef typename std::conditional<is_const, const Node *, Node *>::type NodePtrType; | |
32 typedef typename std::conditional<is_const, const T, T>::type ValueType; | |
26 | 33 |
27 public: | 34 public: |
28 | 35 |
29 iterator( Node *c ); | 36 generic_iterator( NodePtrType c ) : |
37 curr (c) | |
38 { | |
39 } | |
30 | 40 |
31 iterator& operator++(); | 41 generic_iterator & operator++() { |
32 iterator operator++(int); | 42 if ( this->curr != nullptr ) { |
43 this->curr = this->curr->next; | |
44 } | |
45 return *this; | |
46 } | |
33 | 47 |
34 T operator*(); | 48 generic_iterator operator++( int ) { |
35 bool operator!=( typename Queue<T>::iterator ); | 49 auto t = generic_iterator( *this ); |
50 | |
51 if ( this->curr != nullptr ) { | |
52 this->curr = this->curr->next; | |
53 } | |
54 return t; | |
55 } | |
56 | |
57 ValueType operator*() { | |
58 return this->curr->item; | |
59 } | |
60 | |
61 bool operator!=( generic_iterator other ) { | |
62 return this->curr != other.curr; | |
63 } | |
36 | 64 |
37 private: | 65 private: |
38 | 66 |
39 Node *curr; | 67 NodePtrType curr; |
40 }; | 68 }; |
41 | 69 |
42 //////////////////////////////////// | 70 //////////////////////////////////// |
43 | 71 |
44 class const_iterator : public std::iterator<std::forward_iterator_tag, T> { | 72 typedef generic_iterator<true> const_iterator; |
45 | 73 typedef generic_iterator<false> iterator; |
46 public: | |
47 | |
48 const_iterator( const Node *c ); | |
49 | |
50 const_iterator& operator++(); | |
51 const_iterator operator++(int); | |
52 | |
53 const T operator*(); | |
54 bool operator!=( typename Queue<T>::const_iterator ); | |
55 | |
56 private: | |
57 | |
58 const Node *curr; | |
59 }; | |
60 | |
61 //////////////////////////////////// | |
62 | 74 |
63 Queue( void ); | 75 Queue( void ); |
64 ~Queue( void ); | 76 ~Queue( void ); |
65 | 77 |
66 // 1.3.41 Copy constructor. | 78 // 1.3.41 Copy constructor. |
180 template <typename T> | 192 template <typename T> |
181 typename Queue<T>::const_iterator Queue<T>::end( void ) const { | 193 typename Queue<T>::const_iterator Queue<T>::end( void ) const { |
182 return Queue<T>::const_iterator( nullptr ); | 194 return Queue<T>::const_iterator( nullptr ); |
183 } | 195 } |
184 | 196 |
185 | |
186 //////////////////////////////////////////////////////////////////////////////// | |
187 | |
188 template <typename T> | |
189 Queue<T>::iterator::iterator( Node *c ) : | |
190 curr (c) | |
191 { | |
192 } | |
193 | |
194 template <typename T> | |
195 typename Queue<T>::iterator & Queue<T>::iterator::operator++() { | |
196 if ( this->curr != nullptr ) { | |
197 this->curr = this->curr->next; | |
198 } | |
199 return *this; | |
200 } | |
201 | |
202 template <typename T> | |
203 typename Queue<T>::iterator Queue<T>::iterator::operator++( int ) { | |
204 auto t = Queue<T>::iterator( *this ); | |
205 | |
206 if ( this->curr != nullptr ) { | |
207 this->curr = this->curr->next; | |
208 } | |
209 return t; | |
210 } | |
211 | |
212 template <typename T> | |
213 T Queue<T>::iterator::operator*() { | |
214 return this->curr->item; | |
215 } | |
216 | |
217 template <typename T> | |
218 bool Queue<T>::iterator::operator!=( typename Queue<T>::iterator other ) { | |
219 return this->curr != other.curr; | |
220 } | |
221 | |
222 //////////////////////////////////////////////////////////////////////////////// | |
223 | |
224 template <typename T> | |
225 Queue<T>::const_iterator::const_iterator( const Node *c ) : | |
226 curr (c) | |
227 { | |
228 } | |
229 | |
230 template <typename T> | |
231 typename Queue<T>::const_iterator & Queue<T>::const_iterator::operator++() { | |
232 if ( this->curr != nullptr ) { | |
233 this->curr = this->curr->next; | |
234 } | |
235 return *this; | |
236 } | |
237 | |
238 template <typename T> | |
239 typename Queue<T>::const_iterator Queue<T>::const_iterator::operator++( int ) { | |
240 auto t = Queue<T>::const_iterator( *this ); | |
241 | |
242 if ( this->curr != nullptr ) { | |
243 this->curr = this->curr->next; | |
244 } | |
245 return t; | |
246 } | |
247 | |
248 template <typename T> | |
249 const T Queue<T>::const_iterator::operator*() { | |
250 return this->curr->item; | |
251 } | |
252 | |
253 template <typename T> | |
254 bool Queue<T>::const_iterator::operator!=( typename Queue<T>::const_iterator other ) { | |
255 return this->curr != other.curr; | |
256 } | |
257 | |
258 | |
259 #endif | 197 #endif |
260 | 198 |