How to preallocate(reserve) a priority_queue<vector>?
Asked Answered
T

4

20

How can I preallocate a std::priority_queue with a container of type std::vector?

std::priority_queue<unsigned char, std::vector<unsigned char>> pq;
pq.c.reserve(1024);

Does not compile because the underlying vector is a protected member. Is it possible to use the constructor of the priority_queue to wrap it around a pre-reserved vector?

Tipperary answered 24/3, 2015 at 15:1 Comment(0)
D
23

Yes, there's a constructor for that. It's slightly tedious that you also have to specify a comparator:

std::vector<unsigned char> container;
container.reserve(1024);
std::priority_queue<unsigned char, std::vector<unsigned char>> pq (
    std::less<unsigned char>(), std::move(container));

You can also use evil shenanigans to access the protected member, but I wouldn't recommend it.

Documentary answered 24/3, 2015 at 15:12 Comment(2)
Doesn't work for vector<pair<int, int>> container2; container2.reserve(1024); priority_queue<pair<int, int>, vector<pair<int, int>>> minheap (greater<pair<int, int>>(), move(container2));?Stimulate
@HuXixi you have to specify the comparator type in the template arguments: vector<pair<int, int>> container2; container2.reserve(1024); priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int,int>>> minheap (greater<pair<int, int>>(), move(container2));Johnjohna
O
6

Another solution might be to make your own class derived from std::priority_queue, such as:

class MyPQueue : public std::priority_queue<unsigned char, std::vector<unsigned char>>
{
public:
    MyPQueue(size_t reserve_size)
    {
        this->c.reserve(reserve_size);
    }
};

then, in the code, create a MyPQueue object in this way:

MyPQueue mpq(1024);

which object can be upcasted back to the base class whenether needed.

std::priority_queue<unsigned char, std::vector<unsigned char>>& pq = mpq;
Oolite answered 27/3, 2016 at 14:43 Comment(0)
A
3

With C++14, we can write

#include <vector>
#include <queue>
#include <iostream>
#include <utility>
#include <functional>

template <class T>
auto make_reserved(const std::size_t n)
{
  std::vector<T> v;
  v.reserve(n);
  return v;
}

template <class T>
auto make_queue(const std::size_t n)
{
    return std::priority_queue<T>(std::less<T>(), make_reserved<T>(n));
}

int main()
{
  auto q = make_queue<int>(100);
  q.push(1);
  q.push(2);
  std::cout << q.size() << std::endl;
}

Adalai answered 14/9, 2017 at 14:46 Comment(0)
U
1

I don't have enough reputation to comment on Mike Seymour's post, but he ommited the third template argument of std::priority_queue :

std::vector<unsigned char> container;
container.reserve(1024);
std::priority_queue<unsigned char, std::vector<unsigned char>, std::less<unsigned char>> pq(std::less<unsigned char>(), std::move(container));

It is quite verbose for sure, but it does the work.

Urogenital answered 1/7, 2020 at 20:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.