I'm trying to declare a priority queue as a private member so all other methods in the class can access it.
However, I am not able to get this to work with a custom lambda compare function.
Moreover, what is the recommended way of handling such situations?
This works:
private:
priority_queue<int, vector<int>, greater<int>> pq;
This does not work.
private:
static auto comp = [](int n1, int n2) {return (n1 > n2);};
priority_queue<int, vector<int>, decltype(comp)> pq;
If I want to use an STL object with a custom compare function that is accessible by all class methods, how would I do so?
CodePudding user response:
The problem here is a fairly subtle one. Before C 20, lambdas are not default constructible, but from C 20 on, they are. So looking at this:
priority_queue<int, vector<int>, decltype(comp)> pq;
we can see that pq
only knows the type of your comparator and will need to instantiate that type itself. But, before C 20, it cannot because the language doesn't support it.
So, there are two solutions to this, both equally easy:
Add
-std=c 20
to your compiler switches.Change that line of code to:
priority_queue<int, vector<int>, decltype(comp)> pq { comp };
And in fact for option 2, since you are (also) initialising comp
inline, you also need:
static constexpr auto comp = [] (int n1, int n2) { return n1 > n2; };
or:
static inline auto comp = [] (int n1, int n2) { return n1 > n2; };
Both of which need C 17 or later.
Now you have passed as instance of comp
to priority_queue
's (alternative) constructor and so it has what it needs to get the job done.
The reason that std::greater
works is that it's a just a normal functor that std::priority_queue
can construct an instance of when it needs to.
I would also say that it's worth reading this.
And just to round off, the nice thing about using C 20 is that, for one-off cases, you can do things like this:
std::priority_queue<int, std::vector<int>, decltype ([] (int n1, int n2) { return n1 > n2; })> pq;
Which keeps it all neat and tidy.