1

I have the following code that works

auto comp = [&](const auto &x, const auto &y) {
    return a[x] < a[y] || (a[x] == a[y] && x < y);
};
priority_queue <int, vector <int>, decltype(comp)> q(comp); // works
        

And I want to create two of the PQs here like this:

auto comp = [&](const auto &x, const auto &y) {
    return a[x] < a[y] || (a[x] == a[y] && x < y);
};
priority_queue <int, vector <int>, decltype(comp)> q(comp)[2]; // doesn't work
        

so I can't seem to understand what are the semantics here.

For simple PQ declaring an array of them works:

priority_queue <int> q[2]; // works :(
        

Just looking for way to create two lambda queues with indexing q[0] and q[1], but can't seem grasp documentation on it.

*Edit: Thank you everyone!

Could I ask follow up here: what to do if I wanted more queues, some q[N]?

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
Note
  • 19
  • 3
  • 1
    Is this what you are looking for: `priority_queue, decltype(comp)> q[2] = {priority_queue, decltype(comp)>(comp), priority_queue, decltype(comp)>(comp)};` ? – Eldinur the Kolibri Jun 26 '23 at 18:03
  • Yes, thank you! Though I wish there was a simpler way. Can I ask here : what if I wanted to have more than 2 queues, some N queues? – Note Jun 26 '23 at 18:29
  • I guess you could write it in a vector and then emplace_back elements N times in a for loop – Eldinur the Kolibri Jun 26 '23 at 18:38

2 Answers2

3

... q(comp) calls the constructor. If you want an array, just adding [2] after that does not make sense.

What you want is something like priority_queue<int, vector<int>, decltype(comp)> q[2], except you need to initialize the two objects. Here is one way to do it:

using CustomQueue = std::priority_queue<int, std::vector<int>, decltype(comp)>;
CustomQueue q[2] { CustomQueue(comp), CustomQueue(comp) };

Because the constructor of std::priority_queue that takes a comparator is explicit, you cannot use { {comp}, {comp} }.

Answering the edit: if you want n queues, you can always rely on std::vector instead of an array:

std::vector<CustomQueue> q(n, CustomQueue(comp));

If you really want an array, and n is known at compile time, then you can do something like this:

namespace detail
{
    template <typename T, std::size_t ... Is>
    constexpr std::array<T, sizeof...(Is)>
    create_array(T value, std::index_sequence<Is...>)
    {
        // cast Is to void to remove the warning: unused value
        return {{(static_cast<void>(Is), value)...}};
    }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> create_array(const T& value)
{
    return detail::create_array(value, std::make_index_sequence<N>());
}

// ...

auto q = create_array<20>(Queue(comp));

Taken from here

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
2

The initializers of the array go into {} brackets after [2]. Furthermore the constructor you're attempting to use is explicit, so you need to mention the priority queue type in the initializer values as well:

auto comp = [&](const auto& x, const auto& y) {
    return a[x] < a[y] || (a[x] == a[y] && x < y);
};
using PriorityQueue = std::priority_queue<int, std::vector<int>, decltype(comp)>;
PriorityQueue q[2]{ PriorityQueue(comp), PriorityQueue(comp) };
fabian
  • 80,457
  • 12
  • 86
  • 114