/////////////////////////////////////////////////////////////////////////////// // Copyright (c) Electronic Arts Inc. All rights reserved. /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This file implements a queue that is just like the C++ std::queue adapter class. // There are no significant differences between EASTL/queue and std::queue. // We provide this class for completeness and where std STL may not be available. /////////////////////////////////////////////////////////////////////////////// #ifndef EASTL_QUEUE_H #define EASTL_QUEUE_H #include #include #include #include #if defined(EA_PRAGMA_ONCE_SUPPORTED) #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. #endif namespace eastl { /// EASTL_QUEUE_DEFAULT_NAME /// /// Defines a default container name in the absence of a user-provided name. /// #ifndef EASTL_QUEUE_DEFAULT_NAME #define EASTL_QUEUE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " queue" // Unless the user overrides something, this is "EASTL queue". #endif /// EASTL_QUEUE_DEFAULT_ALLOCATOR /// #ifndef EASTL_QUEUE_DEFAULT_ALLOCATOR #define EASTL_QUEUE_DEFAULT_ALLOCATOR allocator_type(EASTL_QUEUE_DEFAULT_NAME) #endif /// queue /// /// queue is an adapter class provides a FIFO (first-in, first-out) interface /// via wrapping a sequence that provides at least the following operations: /// push_back /// pop_front /// front /// back /// /// In practice this usually means deque, list, intrusive_list. vector and string /// cannot be used because they don't provide pop-front. This is reasonable because /// a vector or string pop_front would be inefficient and could lead to /// silently poor performance. /// template > class queue { public: typedef queue this_type; typedef Container container_type; //typedef typename Container::allocator_type allocator_type; // We can't currently declare this because the container may be a type that doesn't have an allocator. typedef typename Container::value_type value_type; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::size_type size_type; public: // We declare public so that global comparison operators can be implemented without adding an inline level and without tripping up GCC 2.x friend declaration failures. GCC (through at least v4.0) is poor at inlining and performance wins over correctness. container_type c; // The C++ standard specifies that you declare a protected member variable of type Container called 'c'. public: queue(); // Allocator is templated here because we aren't allowed to infer the allocator_type from the Container, as some containers (e.g. array) don't // have allocators. For containers that don't have allocator types, you could use void or char as the Allocator template type. template explicit queue(const Allocator& allocator, typename eastl::enable_if::value>::type* = NULL) : c(allocator) { } template queue(const this_type& x, const Allocator& allocator, typename eastl::enable_if::value>::type* = NULL) : c(x.c, allocator) { } template queue(this_type&& x, const Allocator& allocator, typename eastl::enable_if::value>::type* = NULL) : c(eastl::move(x.c), allocator) { } explicit queue(const container_type& x); explicit queue(container_type&& x); // Additional C++11 support to consider: // // template // queue(const container_type& x, const Allocator& allocator); // // template // queue(container_type&& x, const Allocator& allocator); queue(std::initializer_list ilist); // C++11 doesn't specify that std::queue has initializer list support. bool empty() const; size_type size() const; reference front(); const_reference front() const; reference back(); const_reference back() const; void push(const value_type& value); void push(value_type&& x); template EA_DEPRECATED void emplace_back(Args&&... args); // backwards compatibility template decltype(auto) emplace(Args&&... args); void pop(); container_type& get_container(); const container_type& get_container() const; void swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable::value)); bool validate() const; }; // class queue /////////////////////////////////////////////////////////////////////// // queue /////////////////////////////////////////////////////////////////////// template inline queue::queue() : c() // To consider: use c(EASTL_QUEUE_DEFAULT_ALLOCATOR) here, though that would add the requirement that the user supplied container support this. { // Empty } template inline queue::queue(const Container& x) : c(x) { // Empty } template inline queue::queue(Container&& x) : c(eastl::move(x)) { // Empty } template inline queue::queue(std::initializer_list ilist) : c() // We could alternatively use c(ilist) here, but that would require c to have an ilist constructor. { // Better solution but requires an insert function. // c.insert(ilist.begin(), ilist.end()); // Possibly slower solution but doesn't require an insert function. for(typename std::initializer_list::iterator it = ilist.begin(); it != ilist.end(); ++it) { const value_type& value = *it; c.push_back(value); } } template inline bool queue::empty() const { return c.empty(); } template inline typename queue::size_type queue::size() const { return c.size(); } template inline typename queue::reference queue::front() { return c.front(); } template inline typename queue::const_reference queue::front() const { return c.front(); } template inline typename queue::reference queue::back() { return c.back(); } template inline typename queue::const_reference queue::back() const { return c.back(); } template inline void queue::push(const value_type& value) { c.push_back(const_cast(value)); // const_cast so that intrusive_list can work. We may revisit this. } template inline void queue::push(value_type&& x) { c.push_back(eastl::move(x)); } template template inline void queue::emplace_back(Args&&... args) { emplace(eastl::forward(args)...); } template template inline decltype(auto) queue::emplace(Args&&... args) { return c.emplace_back(eastl::forward(args)...); } template inline void queue::pop() { c.pop_front(); } template inline typename queue::container_type& queue::get_container() { return c; } template inline const typename queue::container_type& queue::get_container() const { return c; } template void queue::swap(this_type& x) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable::value)) { using eastl::swap; swap(c, x.c); } template bool queue::validate() const { return c.validate(); } /////////////////////////////////////////////////////////////////////// // global operators /////////////////////////////////////////////////////////////////////// template inline bool operator==(const queue& a, const queue& b) { return (a.c == b.c); } template inline bool operator!=(const queue& a, const queue& b) { return !(a.c == b.c); } template inline bool operator<(const queue& a, const queue& b) { return (a.c < b.c); } template inline bool operator>(const queue& a, const queue& b) { return (b.c < a.c); } template inline bool operator<=(const queue& a, const queue& b) { return !(b.c < a.c); } template inline bool operator>=(const queue& a, const queue& b) { return !(a.c < b.c); } template inline void swap(queue& a, queue& b) EA_NOEXCEPT_IF((eastl::is_nothrow_swappable::container_type>::value)) // EDG has a bug and won't let us use Container in this noexcept statement { a.swap(b); } } // namespace eastl #endif // Header include guard