The code is as following.
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
typedef unordered_map<int,int>::iterator myIt;
class cmpHelper {
public:
bool operator()(myIt l, myIt r){return l->second > r->second;}
};
int main(int argc, char* argv[]){
unordered_map<int,int> freq_cnt({{3,1},{2,4},{5,2}});
priority_queue<myIt,vector<myIt>, cmpHelper> h(freq_cnt.begin(), freq_cnt.end());
//priority_queue<myIt, vector<myIt>, cmpHelper> h;
}
and hereunder shows corresponding compiler info
g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Default constructor is OK. And I tried to go through code under directory /usr/include/c++/7/bits/, but still no any idea. Please help point out what the problem is. Thanks.
2
Answers
It’s because the constructor that takes iterators dereferences the iterators to populate the container.
Put the actual iterators in the container instead:
What you are trying to do would be similar to this:
To clarify further. Check this simplified example:
You use iterators to populate containers by dereferencing (
*beg
above) the iterators. When dereferencing an iterator, you get the value it points at. So, when you dereference an iterator of typestd::vector<int>::iterator
you get a reference to anint
.If you wrap your iterators in iterators that when dereferenced return the original iterators, you can construct the
priority_queue
using those.Example:
then
[freq_cnt.begin(), freq_cnt.end())
is a range ofstd::pair<const int, int>
lvalues, notunordered_map<int,int>::iterator
values.You can create a range of these iterators with C++20’s
std::ranges::iota_view
:Otherwise, you can default construct the queue and push each element:
But consider instead having a queue of references: