如何在priority_queue中使用函子作为自定义比较器

Posted

技术标签:

【中文标题】如何在priority_queue中使用函子作为自定义比较器【英文标题】:How to use functor as custom comparator in priority_queue 【发布时间】:2020-08-27 17:12:42 【问题描述】:

我正在尝试创建一个仿函数作为我的 priority_queue 的自定义比较器,它将 unordered_map 作为构造函数的参数。当我收到错误时,我不确定如何在声明 priority_queue 时调用仿函数:

"Line 22: Char 48: error: template argument for template type parameter must be a type priority_queue 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;
    

【问题讨论】:

【参考方案1】:

TL;DR 版本:

priority_queue<string, vector<string>, compareWords> pq(compareWordswordFreq);

我们是如何到达那里的:

通过简单的解决方案,将比较器传递给pq的构造函数,你会遇到Most Vexing Parse和

priority_queue<string, vector<string>, compareWords> pq(compareWords(wordFreq));
                                       ^class goes here ^ object goes here     

是一个函数定义。呸。通常MVP的解决方案是使用“统一初始化”

priority_queue<string, vector<string>, compareWords> pqcompareWords(wordFreq);
                                                       ^                      ^

但这会触发priority_queue 的初始化列表构造函数。也很恶心。

但是,我们可以在 compareWords 的构造中使用花括号

priority_queue<string, vector<string>, compareWords> pq(compareWordswordFreq);
                                                                    ^        ^  

并避免priority_queue 的初始化列表构造函数重载,同时不要让构造函数误以为我们正在声明一个函数。感谢 Caleth 指出这个技巧。我忽略了它。

【讨论】:

为什么不pq(compareWordswordFreq); 字面意思是因为我没想到。

以上是关于如何在priority_queue中使用函子作为自定义比较器的主要内容,如果未能解决你的问题,请参考以下文章

C++:你在使用 Loki 还是 Boost 作为函子?

STL priority_queue 的自定义分配器

推力::设备向量使用推力::替换或推力::转换与自定义函子/谓词

范畴论-一个单子(Monad)说白了不过就是自函子范畴上的一个幺半群而已

如何在模板类中使用 lambda 作为 STL Compare 方法?

如何将向量传递给基于推力的 odeint 观察者的构造函数,以便可以在函子中读取它