circular_queue.hppGo to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ADOBE_CIRCULAR_QUEUE_HPP
00010 #define ADOBE_CIRCULAR_QUEUE_HPP
00011
00012
00013
00014 #include <adobe/config.hpp>
00015
00016 #include <adobe/algorithm/equal.hpp>
00017 #include <adobe/iterator.hpp>
00018 #include <adobe/move.hpp>
00019
00020 #include <boost/operators.hpp>
00021
00022 #include <cassert>
00023 #include <vector>
00024
00025
00026
00027 namespace adobe {
00207
00208
00209 #if 1 // REVISIT (fbrereto) : Possible compiler optimization?
00210 #define ADOBE_NOTHROW throw()
00211 #else
00212 #define ADOBE_NOTHROW
00213 #endif
00214
00215
00216
00217 template <typename T> class circular_queue;
00218
00219 template <typename T>
00220 bool operator == (const circular_queue<T>& x, const circular_queue<T>& y);
00221
00222 template <typename T>
00223 void swap(circular_queue<T>&, circular_queue<T>&);
00224
00225
00226
00243 template <typename T>
00244 class circular_queue : boost::equality_comparable<circular_queue<T> >
00245 {
00246 public:
00247 typedef T value_type;
00248 typedef T* pointer;
00249 typedef const T* const_pointer;
00250 typedef T& reference;
00251 typedef const T& const_reference;
00252 typedef std::size_t size_type;
00253
00254 circular_queue(std::size_t capacity = 0);
00255
00256 #if !defined(ADOBE_NO_DOCUMENTATION)
00257 circular_queue(const circular_queue& rhs);
00258
00259 circular_queue& operator = (circular_queue rhs);
00260 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00261
00262 size_type size() const ADOBE_NOTHROW;
00263 size_type max_size() const ADOBE_NOTHROW { return container_m.size(); }
00264 size_type capacity() const ADOBE_NOTHROW { return container_m.size(); }
00265
00266 bool empty() const ADOBE_NOTHROW { return is_empty_m; }
00267 bool full() const ADOBE_NOTHROW { return !is_empty_m && begin_m == end_m; }
00268
00269 void clear() ADOBE_NOTHROW { begin_m = end_m; is_empty_m = true; }
00270
00271 reference front() ADOBE_NOTHROW;
00272 const_reference front() const ADOBE_NOTHROW;
00273
00274 template <typename U>
00275 void push_back(const U& x, typename copy_sink<U, T>::type = 0);
00276 template <typename U>
00277 void push_back(U x, typename move_sink<U, T>::type = 0);
00278
00279 void pop_front() ADOBE_NOTHROW;
00280
00281 void putback() ADOBE_NOTHROW;
00282
00283 #if !defined(ADOBE_NO_DOCUMENTATION)
00284 private:
00285 friend inline void swap(circular_queue& x, circular_queue& y)
00286 {
00287 swap(x.container_m, y.container_m);
00288 std::swap(x.begin_m, y.begin_m);
00289 std::swap(x.end_m, y.end_m);
00290 swap(x.is_empty_m, y.is_empty_m);
00291 }
00292
00293 friend bool operator == <> (const circular_queue& x,
00294 const circular_queue& y);
00295
00296 typedef typename std::vector<value_type> container_t;
00297 typedef typename container_t::iterator iterator;
00298 typedef typename container_t::const_iterator const_iterator;
00299
00300
00301 container_t container_m;
00302 iterator begin_m;
00303 iterator end_m;
00304 bool is_empty_m;
00305
00306
00307
00308
00309 typedef std::pair<const_iterator, const_iterator> const_range;
00310
00311 const_range first_range() const
00312 { return const_range(begin_m, begin_m < end_m ? const_iterator(end_m) : boost::end(container_m)); }
00313
00314 const_range second_range() const
00315 { return const_range(begin_m < end_m ? const_iterator(end_m) : boost::begin(container_m), end_m); }
00316
00317 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00318 };
00319
00320
00321
00322 template <typename T>
00323 circular_queue<T>::circular_queue(std::size_t capacity) :
00324 container_m(capacity),
00325 begin_m(boost::begin(container_m)),
00326 end_m(boost::begin(container_m)),
00327 is_empty_m(true)
00328 { }
00329
00330 #if !defined(ADOBE_NO_DOCUMENTATION)
00331
00332
00333
00334 template <typename T>
00335 circular_queue<T>::circular_queue(const circular_queue& rhs) :
00336 container_m (rhs.capacity()),
00337 begin_m (boost::begin(container_m)),
00338 end_m (boost::begin(container_m)),
00339 is_empty_m (rhs.is_empty_m)
00340 {
00341 if (is_empty_m) return;
00342
00343 end_m = copy(rhs.first_range(), end_m);
00344 end_m = copy(rhs.second_range(), end_m);
00345 }
00346
00347
00348
00349 template <typename T>
00350 inline circular_queue<T>& circular_queue<T>::operator = (circular_queue rhs)
00351 { swap(*this, rhs); return *this; }
00352
00353 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00354
00355
00356 template <typename T>
00357 typename circular_queue<T>::reference circular_queue<T>::front() ADOBE_NOTHROW
00358 {
00359 assert(!empty());
00360 return *begin_m;
00361 }
00362
00363
00364
00365 template <typename T>
00366 typename circular_queue<T>::const_reference circular_queue<T>::front() const
00367 ADOBE_NOTHROW
00368 {
00369 assert(!empty());
00370 return *begin_m;
00371 }
00372
00373
00374
00375 template <typename T>
00376 template <typename U>
00377 void circular_queue<T>::push_back(const U& x, typename copy_sink<U, T>::type)
00378 {
00379 *end_m = x;
00380
00381 bool was_full (full());
00382
00383 if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m);
00384 if (was_full) begin_m = end_m;
00385
00386 is_empty_m = false;
00387 }
00388
00389
00390
00391 template <typename T>
00392 template <typename U>
00393 void circular_queue<T>::push_back(U x, typename move_sink<U, T>::type)
00394 {
00395 *end_m = move(x);
00396
00397 bool was_full (full());
00398
00399 if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m);
00400 if (was_full) begin_m = end_m;
00401
00402 is_empty_m = false;
00403 }
00404
00405
00406
00407 template <typename T>
00408 void circular_queue<T>::pop_front() ADOBE_NOTHROW
00409 {
00410 assert(!empty());
00411 if (++begin_m == boost::end(container_m))
00412 begin_m = boost::begin(container_m);
00413 is_empty_m = begin_m == end_m;
00414 }
00415
00416
00417
00418 template <typename T>
00419 void circular_queue<T>::putback() ADOBE_NOTHROW
00420 {
00421 assert(!full());
00422 if (begin_m == boost::begin(container_m))
00423 begin_m = boost::end(container_m);
00424 --begin_m;
00425 is_empty_m = false;
00426 }
00427
00428
00429
00430 template <typename T>
00431 typename circular_queue<T>::size_type circular_queue<T>::size() const ADOBE_NOTHROW
00432 {
00433 if (begin_m < end_m) return std::distance(begin_m, end_m);
00434
00435 return is_empty_m ? 0 : capacity() - std::distance(end_m, begin_m);
00436 }
00437
00438
00439
00440 template <typename T>
00441 bool operator == ( const circular_queue<T>& x,
00442 const circular_queue<T>& y)
00443 {
00444
00445
00446
00447
00448
00449 typedef typename circular_queue<T>::const_range const_range;
00450
00451 if (x.size() != y.size()) return false;
00452
00453 const_range sequence1[] = { x.first_range(), x.second_range() };
00454 const_range sequence2[] = { y.first_range(), y.second_range() };
00455
00456 return equal(make_segmented_range(sequence1),
00457 make_segmented_iterator(sequence2));
00458 }
00459
00460
00461
00462 #undef ADOBE_NOTHROW
00463
00464
00465
00466 }
00467
00468
00469
00470 #endif // ADOBE_CIRCULAR_QUEUE_HPP
00471
00472
|