使用std::find_if遍历multimap时与functor配合出现错误
咱们先拆解你遇到的编译错误原因,再给出针对性的修复方案:
第一个版本代码的核心问题
你的std::multimap<int, int>存储的元素类型是std::pair<const int, int>,但自定义的EqualFunctor<int>::operator()接受的参数是std::pair<const int, int*>——这两个类型完全不匹配,编译器找不到合适的重载函数来调用,于是抛出了no match for call错误。简单说就是:你给functor传了一个它不认识的类型。
第二个版本代码的问题
你修改了pair的类型为std::pair<const int, int*>,但multimap的类型还是std::multimap<int, int>(它的元素类型是std::pair<const int, int>),插入std::pair<const int, int*>会导致类型不兼容(int*无法隐式转换为int);同时你的functor依然只接受std::pair<const int, int*>,和multimap实际存储的元素类型还是不匹配,所以报错依旧。
下面根据你的预期输出(显示0),给出两种可行的修复方案:
方案1:Multimap存储int值(符合你的预期需求)
如果你只是想查找second值等于0的元素,完全不需要用指针,直接比较值即可。修改functor使其匹配multimap的元素类型:
#include <iostream> #include <algorithm> #include <iterator> #include <map> template <typename T> class EqualFunctor { T target_; // 存储要匹配的目标值,而非指针 public: EqualFunctor(T target) : target_(target) {} // 参数匹配multimap的元素类型:std::pair<const int, T> bool operator() (const std::pair<const int, T>& myPair) { return myPair.second == target_; } }; int main() { int f = 0, g = 1, h = 0, i = 1, j = 1; std::pair<const int, int> myPairA (1, f), myPairB (2, g), myPairC (3, h), myPairD (4, i), myPairE (5, j); std::multimap<int, int> myMultimap; myMultimap.insert(myPairB); myMultimap.insert(myPairC); myMultimap.insert(myPairD); myMultimap.insert(myPairE); std::multimap<int, int>::iterator it; // 直接传入要匹配的值0,无需指针 it = std::find_if(myMultimap.begin(), myMultimap.end(), EqualFunctor<int>(f)); if (it != myMultimap.end()) { // 必须检查迭代器是否合法,避免访问空元素 std::cout << it->second << std::endl; // 输出0,符合预期 } else { std::cout << "Element not found" << std::endl; } return 0; }
方案2:Multimap存储int指针(若你确实需要存储指针)
如果你必须在multimap中存储指针,需要同步修改multimap的类型、插入元素的类型,以及functor的参数匹配:
#include <iostream> #include <algorithm> #include <iterator> #include <map> template <typename T> class EqualFunctor { T* target_ptr_; // 存储要匹配的目标指针 public: EqualFunctor(T* target_ptr) : target_ptr_(target_ptr) {} // 参数匹配multimap的元素类型:std::pair<const int, T*> bool operator() (const std::pair<const int, T*>& myPair) { return myPair.second == target_ptr_; } }; int main() { int f = 0, g = 1, h = 0, i = 1, j = 1; int* ptrF = &f, *ptrG = &g, *ptrH = &h, *ptrI = &i, *ptrJ = &j; // 声明pair时使用int*作为second类型 std::pair<const int, int*> myPairA (1, ptrF), myPairB (2, ptrG), myPairC (3, ptrH), myPairD (4, ptrI), myPairE (5, ptrJ); // 修改multimap类型为<int, int*> std::multimap<int, int*> myMultimap; myMultimap.insert(myPairB); myMultimap.insert(myPairC); myMultimap.insert(myPairD); myMultimap.insert(myPairE); std::multimap<int, int*>::iterator it; // 传入要匹配的指针 it = std::find_if(myMultimap.begin(), myMultimap.end(), EqualFunctor<int>(myPairA.second)); if (it != myMultimap.end()) { std::cout << *(it->second) << std::endl; // 解引用指针得到0,符合预期 } else { std::cout << "Element not found" << std::endl; } return 0; }
额外简化建议:使用Lambda表达式
在C++11及以后的版本中,你可以用Lambda替代自定义functor,代码会更简洁易读:
对于方案1,std::find_if可以直接写成:
it = std::find_if(myMultimap.begin(), myMultimap.end(), [f](const std::pair<const int, int>& elem) { return elem.second == f; });
这样就不需要单独定义EqualFunctor类了。
内容的提问来源于stack exchange,提问作者JassP

