// bslstl_priorityqueue.h -*-C++-*- #ifndef INCLUDED_BSLSTL_PRIORITYQUEUE #define INCLUDED_BSLSTL_PRIORITYQUEUE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide container adapter class template 'priority_queue'. // //@CLASSES: // bsl::priority_queue: template of highest-priority-first data structure // //@CANONICAL_HEADER: bsl_queue.h // //@SEE_ALSO: bslstl_queue, bslstl_stack // //@DESCRIPTION: This component defines a class template, 'bsl::priority_queue', // holding a container (of a template parameter type, 'CONTAINER', containing // elements of another template parameter type, 'VALUE'), and adapting it to // provide highest-priority-first priority queue data structure. The component // takes a third template parameter type, 'COMPARATOR', for customized // priorities comparison between two elements. // // An instantiation of 'priority_queue' is an allocator-aware, value-semantic // type whose salient attributes are its size (number of held elements) and the // sorted sequence of values (of held elements). If 'priority_queue' is // instantiated with a value type, that is not itself value-semantic, then it // will not retain all of its value-semantic qualities. A 'priority_queue' // cannot be tested for equality, but its value type must be able to be tested // for comparing less by its comparator type. // // The 'priority_queue' implemented here adheres to the C++11 standard when // compiled with a C++11 compiler, and makes the best approximation when // compiled with a C++03 compiler. In particular, for C++03 we emulate move // semantics, but limit forwarding (in 'emplace') to 'const' lvalues, and make // no effort to emulate 'noexcept' or initializer-lists. // ///Memory Allocation ///----------------- // The type supplied as an 'ALLOCATOR' template parameter in some of // 'priority_queue' constructors determines how the held container (of the // (template parameter) type 'CONTAINER') will allocate memory. A // 'priority_queue' supports allocators meeting the requirements of the C++11 // standard [17.6.3.5] as long as the held container does. In addition it // supports scoped-allocators derived from the 'bslma::Allocator' memory // allocation protocol. Clients intending to use 'bslma'-style allocators // should use 'bsl::allocator' as the 'ALLOCATOR' template parameter, // providing a C++11 standard-compatible adapter for a 'bslma::Allocator' // object. // ///'VALUE' and 'CONTAINER::value_type' ///- - - - - - - - - - - - - - - - - - // When the 'CONTAINER' template parameter is omitted the 'VALUE' template // parameter specifies the 'value_type' of 'bsl::vector', the default container // type. The 'VALUE' template has no other role. // // For C++17 and later, the behavior is undefined unless: //.. // true == bsl::is_same<VALUE, typename CONTAINER::value_type>::value //.. // Prior to C++17, 'CONTAINER::value_type' determines the contained value type // and 'VALUE' is simply ignored. The resulting code may work with instances // of 'VALUE' (e.g., 'VALUE' is convertible to 'CONTAINER::value_type') or not // (compiler errors). // ///Operations ///---------- // The C++11 standard [23.6.4] declares any container type supporting // operations 'front', 'push_back', and 'pop_back' can be used to instantiate // the (template parameter) type 'CONTAINER'. Below is a list of public // methods of 'priority_queue' class that are effectively implemented as // calling the corresponding operations in the held container (referenced as // 'c'). //.. // +--------------------------------------+--------------------------+ // | Public methods in 'priority_queue' | Operation in 'CONTAINER' | // +======================================+==========================+ // | void push(const value_type& value); | c.push_back(value); | // | void pop(); | c.pop_back(); | // | void emplace(Args&&... args) | c.emplace_back(...) | // +--------------------------------------+--------------------------+ // | bool empty() const; | c.empty(); | // | size_type size() const; | c.size(); | // | const_reference top() const; | c.front(); | // +--------------------------------------+--------------------------+ //.. // ///Usage ///----- // In this section we show intended use of this component. // ///Example 1: Task Scheduler ///- - - - - - - - - - - - - // In this example, we will use the 'bsl::priority_queue' class to implement a // task scheduler that schedules a group of tasks based on their designated // priorities. // // Suppose we want to write a background process that runs tasks needed by // foreground applications. Each task has a task id, a priority, and a // function pointer that can be invoked by the background process. This // background process has two threads: one thread (receiving thread) receives // requests from other applications, passing required tasks to a task // scheduler; the other thread (processing thread) runs the task scheduler, // executing the tasks one-by-one from higher to lower priorities. To // implement this functionality, we can use 'bsl::priority_queue' in the task // scheduler to buffer received, but as yet unprocessed, tasks. The task // scheduler adds newly received tasks into the priority queue in the receiving // thread, and extracts tasks from the priority queue for execution according // to their priorities in the processing thread. // // First, we define a 'TaskFunction' type: //.. // typedef void (*TaskFunction)(int, int, int); //.. // Then, we define a 'Task' class, which contains a task id, a 'TaskFunction' // object and an associated task priority: //.. // class Task // // This class represents a task that has an integer task id, a task // // function, and an integer priority. The smaller the numerical value // // of a priority, the higher the priority. // { // private: // // DATA // int d_taskId; // task id // // TaskFunction d_taskFunction_p; // task function // // int d_priority; // priority of the task // // public: // // CREATORS // explicit Task(int taskId, TaskFunction taskFunction, int priority); // // Create a 'Task' object having the specified 'taskId', the // // specified 'd_taskFunction_p', and the specified 'priority'. // // // ACCESSORS // int getId() const; // // Return the contained task id. // // int getPriority() const; // // Return the priority of the task. // // TaskFunction getFunction() const; // // Return the contained task function object. // }; // // // CREATORS // Task::Task(int taskId, TaskFunction taskFunction, int priority) // : d_taskId(taskId) // , d_taskFunction_p(taskFunction) // , d_priority(priority) // { // } // // // ACCESSORS // inline // int Task::getId() const // { // return d_taskId; // } // // inline // int Task::getPriority() const // { // return d_priority; // } // // inline // TaskFunction Task::getFunction() const // { // return d_taskFunction_p; // } //.. // Next, we define a functor to compare the priorities of two 'Task' objects: //.. // struct TaskComparator { // // This 'struct' defines an ordering on 'Task' objects, allowing them // // to be included in sorted data structures such as // // 'bsl::priority_queue'. // // bool operator()(const Task& lhs, const Task& rhs) const // // Return 'true' if the priority of the specified 'lhs' is // // numerically less than that of the specified 'rhs', and 'false' // // otherwise. Note that the smaller the value returned by the // // 'Task::getPriority' method, the higher the priority. // { // return lhs.getPriority() > rhs.getPriority(); // } // }; //.. // Then, we define a 'TaskScheduler' class that provides methods to hold and // schedule unprocessed tasks: //.. // class TaskScheduler { // // This class holds and schedules tasks to execute. //.. // Here, we define a private data member that is an instantiation of // 'bsl::priority_queue', which uses 'Task' for its 'VALUE' (template // parameter) type, 'bsl::vector<Task>' for its 'CONTAINER' (template // parameter) type, and 'TaskComparator' for its 'COMPARATOR' (template // parameter) type: //.. // // DATA // bsl::priority_queue<Task, // bsl::vector<Task>, // TaskComparator> // d_taskPriorityQueue; // priority queue holding unprocessed tasks // // // ... // // public: // // CREATORS // explicit TaskScheduler(bslma::Allocator *basicAllocator = 0); // // Create a 'TaskScheduler' object. Optionally specify a // // 'basicAllocator' used to supply memory. If 'basicAllocator' is // // 0, the currently installed default allocator is used. // // // MANIPULATORS // void addTask(int taskId, TaskFunction taskFunction, int priority); // // Enqueue the specified 'task' having the specified 'priority' // // onto this scheduler. // // void processTasks(int verbose); // // Dequeue the task having the highest priority in this scheduler, // // and call its task function by passing in the specified 'verbose' // // flag. // }; //.. // Next, we implement the 'TaskScheduler' constructor: //.. // TaskScheduler::TaskScheduler(bslma::Allocator *basicAllocator) // : d_taskPriorityQueue(basicAllocator) // { // } //.. // Notice that we pass to the contained 'd_taskPriorityQueue' object the // 'bslma::Allocator' supplied to the 'TaskScheduler' at construction. // // Then, we implement the 'addTask' method, which constructs a 'Task' object // and adds it into the priority queue: //.. // void TaskScheduler::addTask(int taskId, // TaskFunction taskFunction, // int priority) // { // // ... (some synchronization) // // d_taskPriorityQueue.push(Task(taskId, taskFunction, priority)); // // // ... // } //.. // Next, we implement the 'processTasks' method, which extracts tasks from the // priority queue in order of descending priorities, and executes them: //.. // void TaskScheduler::processTasks(int verbose) // { // // ... (some synchronization) // // while (!d_taskPriorityQueue.empty()) { // const Task& task = d_taskPriorityQueue.top(); // TaskFunction taskFunction = task.getFunction(); // if (taskFunction) { // taskFunction(task.getId(), task.getPriority(), verbose); // } // d_taskPriorityQueue.pop(); // } // // // ... // } //.. // Note that the 'top' method always returns the 'Task' object having the // highest priority in the priority queue. // // Then, we define two task functions: //.. // void taskFunction1(int taskId, int priority, int verbose) // { // if (verbose) { // printf("Executing task %d (priority = %d) in 'taskFunction1'.\n", // taskId, // priority); // } // } // // void taskFunction2(int taskId, int priority, int verbose) // { // if (verbose) { // printf("Executing task %d (priority = %d) in 'taskFunction2'.\n", // taskId, // priority); // } // } //.. // Next, we create a global 'TaskScheduler' object: //.. // TaskScheduler taskScheduler; //.. // Now, we call the 'addTask' method of 'taskScheduler' in the receiving // thread: //.. // // (in receiving thread) // // ... // // taskScheduler.addTask(1, taskFunction1, 50); // // // ... // // taskScheduler.addTask(2, taskFunction1, 99); // // // ... // // taskScheduler.addTask(3, taskFunction2, 4); // // // ... //.. // Finally, we call the 'processTasks' method of 'taskScheduler' in the // processing thread: //.. // // (in processing thread) // // ... // // taskScheduler.processTasks(veryVerbose); // // // ... //.. #include <bslscm_version.h> #include <bslstl_vector.h> #include <bslstl_iteratorutil.h> #include <bslalg_swaputil.h> #include <bslma_isstdallocator.h> #include <bslma_stdallocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_assert.h> #include <bslmf_enableif.h> #include <bslmf_isconvertible.h> #include <bslmf_issame.h> #include <bslmf_movableref.h> #include <bslmf_nestedtraitdeclaration.h> #include <bslmf_usesallocator.h> #include <bslmf_util.h> // 'forward(V)' #include <bsls_compilerfeatures.h> #include <bsls_keyword.h> #include <bsls_libraryfeatures.h> #include <bsls_util.h> // 'forward<T>(V)' #include <algorithm> #include <functional> #if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // Include version that can be compiled with C++03 // Generated on Thu Oct 21 10:11:37 2021 // Command line: sim_cpp11_features.pl bslstl_priorityqueue.h # define COMPILING_BSLSTL_PRIORITYQUEUE_H # include <bslstl_priorityqueue_cpp03.h> # undef COMPILING_BSLSTL_PRIORITYQUEUE_H #else namespace bsl { // ==================== // class priority_queue // ==================== template <class VALUE, class CONTAINER = vector<VALUE>, class COMPARATOR = std::less<typename CONTAINER::value_type> > class priority_queue { // This class is a value-semantic class template, adapting a container of // the (template parameter) type 'CONTAINER', that holds elements of the // (template parameter) type 'VALUE', to provide a highest-priority-first // priority queue data structure, where the priorities of elements are // compared by a comparator of the template parameter type, 'COMPARATOR'. // The container object held by a 'priority_queue' class object is // referenced as 'c' in the following documentation. #ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY // STATIC CHECK: Type mismatch is UB per C++17 BSLMF_ASSERT((is_same<VALUE, typename CONTAINER::value_type>::value)); #endif private: // PRIVATE TYPES typedef BloombergLP::bslmf::MovableRefUtil MoveUtil; // This 'typedef' is a convenient alias for the utility associated with // movable references. public: // PUBLIC TYPES typedef CONTAINER container_type; typedef COMPARATOR value_compare; 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; protected: // PROTECTED DATA CONTAINER c; // container for elements in the 'priority_queue'. This // data member exactly matches its definition in the // C++11 standard [23.6.4]. COMPARATOR comp; // comparator that defines the priority order of elements // in the 'priority_queue'. This data member exactly // matches its definition in the C++11 standard [23.6.4]. public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION_IF( priority_queue, BloombergLP::bslma::UsesBslmaAllocator, BloombergLP::bslma::UsesBslmaAllocator<container_type>::value); // CREATORS priority_queue(); // Create an empty priority queue, adapting a default-constructed // container of the (template parameter) type 'CONTAINER'. Use a // default-constructed comparator of the (template parameter) type // 'COMPARATOR' to order elements in the priority queue. explicit priority_queue(const COMPARATOR& comparator); // Create an empty priority queue, adapting a default-constructed // container of the (template parameter) type 'CONTAINER', and having // the specified 'comparator' of the (template parameter) type // 'COMPARATOR' to order elements in the priority queue. priority_queue(const COMPARATOR& comparator, const CONTAINER& container); // Create a priority queue, adapting the specified 'container' of the // (template parameter) type 'CONTAINER', and having the specified // 'comparator' of the (template parameter) type 'COMPARATOR' to order // elements in the priority queue. explicit priority_queue( const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container); // Create a priority queue, adapting the specified 'container' of the // (template parameter) type 'CONTAINER', and having the specified // 'comparator' of the (template parameter) type 'COMPARATOR' to order // elements in the priority queue. template <class INPUT_ITERATOR> priority_queue(INPUT_ITERATOR first, INPUT_ITERATOR last); // Create a priority queue, adapting a default-constructed container of // the (template parameter) type 'CONTAINER', and inserting into the // container a sequence of 'value_type' elements that starts at the // specified 'first' and ends immediately before the specified 'last'. // Use a default-constructed comparator of the (template parameter) // type 'COMPARATOR' to order elements in the priority queue. template <class INPUT_ITERATOR> priority_queue(INPUT_ITERATOR first, INPUT_ITERATOR last, const COMPARATOR& comparator, const CONTAINER& container); // Create a priority queue, adapting the specified 'container', having // the specified 'comparator' to order the priorities of elements, // including those originally existed in 'container', and those // inserted into the 'container' from a sequence of 'value_type' // elements starting at the specified 'first', and ending immediately // before the specified 'last'. template <class INPUT_ITERATOR> priority_queue( INPUT_ITERATOR first, INPUT_ITERATOR last, const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container); // Create a priority queue, adapting the specified 'container', having // the specified 'comparator' to order elements in the priority queue, // including those originally existed in 'container', and those // inserted into the 'container' from a sequence of 'value_type' // elements starting at the specified 'first', and ending immediately // before the specified 'last'. priority_queue(const priority_queue& original); // Create a priority queue having the same value as the specified // 'original' object. Use a copy of the comparator from 'original' to // order elements in the priority queue. priority_queue(BloombergLP::bslmf::MovableRef<priority_queue> original); // Create a priority queue having the same value as the specified // 'original' object. Use a copy of the comparator from 'original' to // order elements in the priority queue. template <class ALLOCATOR> explicit priority_queue(const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create an empty priority queue, adapting a default-constructed // container of the (template parameter) type 'CONTAINER' that uses the // specified 'basicAllocator' to supply memory. Use a // default-constructed object of the (template parameter) type // 'COMPARATOR' to order elements in the priority queue. Note that // this constructor is only defined if the underlying container uses // allocator. Otherwise this constructor is disabled. template <class ALLOCATOR> priority_queue(const COMPARATOR& comparator, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create an empty priority queue, adapting a default-constructed // container of the (template parameter) type 'CONTAINER' that uses the // specified 'basicAllocator' to supply memory, and the specified // 'comparator' to order elements in the priority queue. Note that // this constructor is only defined if the underlying container uses // allocator. Otherwise this constructor is disabled. template <class ALLOCATOR> priority_queue(const COMPARATOR& comparator, const CONTAINER& container, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create a priority queue, adapting the specified 'container' that // uses the specified 'basicAllocator' to supply memory, and the // specified 'comparator' to order elements in the priority queue. // Note that this constructor is only defined if the underlying // container uses allocator. Otherwise this constructor is disabled. template <class ALLOCATOR> priority_queue(const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create a priority queue, adapting the specified 'container' that // uses the specified 'basicAllocator' to supply memory, and the // specified 'comparator' to order elements in the priority queue. // Note that this constructor is only defined if the underlying // container uses allocator. Otherwise this constructor is disabled. template <class ALLOCATOR> priority_queue(const priority_queue& original, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create a priority queue having the same value as the specified // 'original' object and using the specified 'basicAllocator' to supply // memory. Use a copy of the comparator from 'original' to order // elements in the priority queue. Note that this constructor is only // defined if the underlying container uses allocator. Otherwise this // constructor is disabled. template <class ALLOCATOR> priority_queue( BloombergLP::bslmf::MovableRef<priority_queue> original, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type * = 0); // Create a priority queue having the same value as the specified // 'original' object and using the specified 'basicAllocator' to supply // memory. Use a copy of the comparator from 'original' to order // elements in the priority queue. Note that this constructor is only // defined if the underlying container uses allocator. Otherwise this // constructor is disabled. // MANIPULATORS priority_queue& operator=(const priority_queue& rhs); // Assign to this object the value and comparator of the specified // 'rhs' object and return a reference providing modifiable access to // this object. priority_queue& operator=( BloombergLP::bslmf::MovableRef<priority_queue> rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false); // Assign to this object the value and comparator of the specified // 'rhs' object and return a reference providing modifiable access to // this object. 'rhs' is left in a valid but unspecified state. void push(const value_type& value); // Insert the specified 'value' into this priority queue. In effect, // performs 'c.push_back(value);'. void push(BloombergLP::bslmf::MovableRef<value_type> value); // Insert the specified 'value' into this priority queue. In effect, // performs 'c.push_back(value);'. #if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES template <class... Args> void emplace(Args&&... args); // Insert into this priority queue a newly created 'value_type' object, // constructed by forwarding the specified (variable number of) 'args' // to the corresponding constructor of 'value_type'. In effect, // performs 'c.emplace_back(FORWARD(Args,args)...);'. #endif void pop(); // Remove the top element from this 'priority_queue' object that has // the highest priority. In effect, performs 'c.pop_back();'. The // behavior is undefined if there is currently no elements in this // object. void swap(priority_queue& other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION( bsl::is_nothrow_swappable<CONTAINER>::value && bsl::is_nothrow_swappable<COMPARATOR>::value); // Efficiently exchange the value of this object with the value of the // specified 'other' object. In effect, performs 'using bsl::swap; // swap(c, other.c);'. // ACCESSORS bool empty() const; // Return 'true' if this 'priority_queue' object contains no elements, // and 'false' otherwise. In effect, performs 'return c.empty();'. size_type size() const; // Return the number of elements in this 'priority_queue' object. In // effect, performs 'return c.size()'. const_reference top() const; // Return a reference providing non-modifiable access to the element // having the highest priority in this 'priority_queue' object. In // effect, performs 'return c.front()'. The behavior is undefined if // the priority queue is empty. }; #ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD // CLASS TEMPLATE DEDUCTION GUIDES template < class COMPARATOR, class CONTAINER, class = bsl::enable_if_t<!bsl::IsStdAllocator_v<CONTAINER>> > priority_queue(COMPARATOR, CONTAINER) -> priority_queue<typename CONTAINER::value_type, CONTAINER, COMPARATOR>; // Deduce the template parameter 'VALUE' and 'CONTAINER' from the // parameters supplied to the constructor of 'priority_queue'. template < class COMPARATOR, class CONTAINER, class ALLOCATOR, class = bsl::enable_if_t<bsl::uses_allocator_v<CONTAINER, ALLOCATOR>> > priority_queue(COMPARATOR, CONTAINER, ALLOCATOR) -> priority_queue<typename CONTAINER::value_type, CONTAINER, COMPARATOR>; // Deduce the template parameters 'VALUE', 'CONTAINER' and 'COMPARATOR' // from the parameters supplied to the constructor of 'priority_queue'. // This deduction guide does not participate unless the supplied allocator // is convertible to the underlying container's 'allocator_type'. template < class INPUT_ITERATOR, class VALUE = typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR> > priority_queue(INPUT_ITERATOR, INPUT_ITERATOR) -> priority_queue<VALUE>; // Deduce the template parameter 'VALUE' from the 'value_type' of the // iterators supplied to the constructor of 'priority_queue'. template < class INPUT_ITERATOR, class COMPARATOR, class CONTAINER, class VALUE = typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR> > priority_queue(INPUT_ITERATOR, INPUT_ITERATOR, COMPARATOR, CONTAINER) -> priority_queue<VALUE, CONTAINER, COMPARATOR>; // Deduce the template parameter 'VALUE' from the 'value_type' of the // iterators supplied to the constructor of 'priority_queue'. Deduce the // template parameters 'CONTAINER' and 'COMPARATOR' from the other // parameters passed to the constructor. #endif // FREE FUNCTIONS template <class VALUE, class CONTAINER, class COMPARATOR> void swap(priority_queue<VALUE, CONTAINER, COMPARATOR>& a, priority_queue<VALUE, CONTAINER, COMPARATOR>& b) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false); // Exchange the container and comparator of the specified 'a' object with // the container and comparator of the specified 'b' object. // ============================================================================ // TEMPLATE AND INLINE FUNCTION DEFINITIONS // ============================================================================ // -------------------- // class priority_queue // -------------------- // CREATORS template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue() { } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator) : comp(comparator) { } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator, const CONTAINER& container) : c(container) , comp(comparator) { std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container) : c(MoveUtil::move(container)) , comp(comparator) { std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> template <class INPUT_ITERATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( INPUT_ITERATOR first, INPUT_ITERATOR last) { c.insert(c.end(), first, last); std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> template <class INPUT_ITERATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( INPUT_ITERATOR first, INPUT_ITERATOR last, const COMPARATOR& comparator, const CONTAINER& container) : c(container) , comp(comparator) { c.insert(c.end(), first, last); std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> template <class INPUT_ITERATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( INPUT_ITERATOR first, INPUT_ITERATOR last, const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container) : c(MoveUtil::move(container)) , comp(comparator) { c.insert(c.end(), first, last); std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const priority_queue& original) : c(original.c) , comp(original.comp) { } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( BloombergLP::bslmf::MovableRef<priority_queue> original) : c(MoveUtil::move(MoveUtil::access(original).c)) , comp(MoveUtil::access(original).comp) { } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(basicAllocator) , comp(COMPARATOR()) { } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(basicAllocator) , comp(comparator) { } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator, const CONTAINER& container, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(container, basicAllocator) , comp(comparator) { std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const COMPARATOR& comparator, BloombergLP::bslmf::MovableRef<CONTAINER> container, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(MoveUtil::move(container), basicAllocator) , comp(comparator) { std::make_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( const priority_queue& original, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(original.c, basicAllocator) , comp(original.comp) { } template <class VALUE, class CONTAINER, class COMPARATOR> template <class ALLOCATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>::priority_queue( BloombergLP::bslmf::MovableRef<priority_queue> original, const ALLOCATOR& basicAllocator, typename enable_if< bsl::uses_allocator<CONTAINER, ALLOCATOR>::value, ALLOCATOR>::type *) : c(MoveUtil::move(MoveUtil::access(original).c), basicAllocator) , comp(MoveUtil::access(original).comp) { } // MANIPULATORS template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>& priority_queue<VALUE, CONTAINER, COMPARATOR>::operator=( const priority_queue& rhs) { c = rhs.c; comp = rhs.comp; return *this; } template <class VALUE, class CONTAINER, class COMPARATOR> inline priority_queue<VALUE, CONTAINER, COMPARATOR>& priority_queue<VALUE, CONTAINER, COMPARATOR>::operator=( BloombergLP::bslmf::MovableRef<priority_queue> rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false) { c = MoveUtil::move(MoveUtil::access(rhs).c); comp = MoveUtil::access(rhs).comp; return *this; } template <class VALUE, class CONTAINER, class COMPARATOR> inline void priority_queue<VALUE, CONTAINER, COMPARATOR>::push( const value_type& value) { c.push_back(value); std::push_heap(c.begin(), c.end(), comp); } template <class VALUE, class CONTAINER, class COMPARATOR> inline void priority_queue<VALUE, CONTAINER, COMPARATOR>::push( BloombergLP::bslmf::MovableRef<value_type> value) { c.push_back(MoveUtil::move(value)); std::push_heap(c.begin(), c.end(), comp); } #if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES template <class VALUE, class CONTAINER, class COMPARATOR> template <class... Args> inline void priority_queue<VALUE, CONTAINER, COMPARATOR>::emplace(Args&&... args) { c.emplace_back(BSLS_COMPILERFEATURES_FORWARD(Args,args)...); std::push_heap(c.begin(), c.end(), comp); } #endif template <class VALUE, class CONTAINER, class COMPARATOR> inline void priority_queue<VALUE, CONTAINER, COMPARATOR>::pop() { std::pop_heap(c.begin(), c.end(), comp); c.pop_back(); } template <class VALUE, class CONTAINER, class COMPARATOR> inline void priority_queue<VALUE, CONTAINER, COMPARATOR>::swap(priority_queue& other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION( bsl::is_nothrow_swappable<CONTAINER>::value && bsl::is_nothrow_swappable<COMPARATOR>::value) { BloombergLP::bslalg::SwapUtil::swap(&c, &other.c); BloombergLP::bslalg::SwapUtil::swap(&comp, &other.comp); } // ACCESSORS template <class VALUE, class CONTAINER, class COMPARATOR> inline bool priority_queue<VALUE, CONTAINER, COMPARATOR>::empty() const { return c.empty(); } template <class VALUE, class CONTAINER, class COMPARATOR> inline typename priority_queue<VALUE, CONTAINER, COMPARATOR>::size_type priority_queue<VALUE, CONTAINER, COMPARATOR>::size() const { return c.size(); } template <class VALUE, class CONTAINER, class COMPARATOR> inline typename priority_queue<VALUE, CONTAINER, COMPARATOR>::const_reference priority_queue<VALUE, CONTAINER, COMPARATOR>::top() const { return c.front(); } // FREE FUNCTIONS template <class VALUE, class CONTAINER, class COMPARATOR> void swap(priority_queue<VALUE, CONTAINER, COMPARATOR>& a, priority_queue<VALUE, CONTAINER, COMPARATOR>& b) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(false) { a.swap(b); } } // close namespace bsl #endif // End C++11 code #endif // ---------------------------------------------------------------------------- // Copyright 2016 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------