I am trying to create a functor as custom comparator for my priority_queue which takes in an unordered_map as a parameter for constructor. I am not sure how to call the functor when declaring the priority_queue as I am getting the error:
"Line 22: Char 48: error: template argument for template type parameter must be a type priority_queue<string, vector, compareWords(wordFreq)> pq;"
class compareWords{
public:
compareWords(unordered_map<string, int> &wordCounts): wordFreq(wordCounts){}
bool operator()(string word1, string word2){
if(wordFreq[word1] == wordFreq[word2]){
return word1 < word2;
}
return wordFreq[word1] < wordFreq[word2];
}
private:
unordered_map<string, int> wordFreq;
};
vector<string> topKFrequent(vector<string>& words, int k) {
vector<string> result;
unordered_map<string, int> wordFreq;
for(int i = 0; i < words.size(); i++){
wordFreq[words[i]]++;
}
priority_queue<string, vector<string>, compareWords(wordFreq)> pq;
for(auto& item: wordFreq){
pq.push(item.first);
}
for(int i = 0; i < k; i++){
result.push_back(pq.top());
pq.pop();
}
return result;
}
priority_queue<string, vector<string>, compareWords> pq(compareWords{wordFreq});
With the trivial solution, pass the comparator into pq
's constructor, you encounter the Most Vexing Parse and
priority_queue<string, vector<string>, compareWords> pq(compareWords(wordFreq));
^class goes here ^ object goes here
is a function definition. Yuck. Normally the solution to MVP is to use "uniform initialization"
priority_queue<string, vector<string>, compareWords> pq{compareWords(wordFreq)};
^ ^
but this triggers priority_queue
's Initialization list constructor. Also yuck.
However, we can use the curly braces on compareWords
's construction instead
priority_queue<string, vector<string>, compareWords> pq(compareWords{wordFreq});
^ ^
and avoid priority_queue
's initialization list constructor overload while not fooling the constructor into thinking we're declaring a function. Thank you to Caleth for pointing this trick out. I'd overlooked it.