C++自定义容器用std::find/find_if查找对象报C2064错误解决方法
错误原因
两个版本的代码分别存在逻辑错误:
- 第一版用
std::find的逻辑不成立:std::find的匹配规则是将遍历到的容器元素直接与第三个传入值做==比较。你的容器存储的是WindowWithTitleButton类型对象,传入的待匹配值是string类型,二者没有定义对应的相等比较运算符,根本无法完成匹配。 - 第二版触发C2064编译错误的核心原因是
std::find_if的第三个参数传参完全不符合要求:std::find_if要求第三个参数是接收1个参数(即当前遍历到的容器元素)、返回可转换为bool类型值的可调用对象。你传入的ContainsTitle((*iter).GetTitle(),title_find)是一次即时函数调用,最终传入的是该函数返回的bool类型结果,不是可调用对象;编译器拿到一个bool值自然无法将其作为函数调用,就会抛出“项不会计算为接受1个参数的函数”的错误。
另外你实现的ContainsTitle本身设计也有问题:作为类成员函数它会隐式携带this指针,不能直接作为谓词传给STL算法,且参数逻辑错误——谓词只需要接收当前遍历到的容器元素即可,不需要提前传入迭代器指向的元素值。
正确实现方案
推荐写法(C++11及以上版本)
不需要单独定义ContainsTitle函数,直接在find_if中传入lambda表达式作为谓词,代码最简洁直观:
#include <algorithm> MyIterator<WindowWithTitleButton> WindowList::FindTitle(const string& title_find) { return std::find_if(begin(), end(), [&title_find](const WindowWithTitleButton& wnd) { return wnd.GetTitle() == title_find; }); }
lambda通过引用捕获要查找的目标title,每次遍历到窗口对象时,自动取对象的title属性和目标值比对,完全符合find_if对谓词的参数要求。
兼容旧标准写法(无C++11支持场景)
如果编译器不支持lambda,自定义仿函数(重载了()运算符的结构体)作为谓词,提前把待匹配的title存入仿函数实例即可:
// 定义为WindowList的私有内部类型,或全局匿名命名空间下的辅助类型 struct MatchWindowTitle { string target; explicit MatchWindowTitle(const string& t): target(t) {} bool operator()(const WindowWithTitleButton& wnd) const { return wnd.GetTitle() == target; } }; MyIterator<WindowWithTitleButton> WindowList::FindTitle(const string& title_find) { return std::find_if(begin(), end(), MatchWindowTitle(title_find)); }
优化提示
- 原代码中
iter = begin(), iter = end()的赋值写法完全多余,直接将begin()、end()返回的迭代器作为参数传入find_if即可。 - 字符串参数尽量用
const string&传递,避免不必要的内存拷贝。 - 字符串相等判断直接用
==即可,不需要手动调用compare方法判断返回值是否为0,二者逻辑完全等价,前者可读性更好。
内容的提问来源于stack exchange,提问作者alex_shevch
相关产品推荐
相关产品推荐

