std::list谓词调用成员函数触发Error C3867编译错误咨询
错误原理
触发C3867编译错误的核心原因是非静态成员函数不能直接作为普通谓词传入算法接口:
std::list::remove_if要求传入的谓词是仅接收1个列表元素类型参数、返回bool的可调用对象。- 你定义的
single_digit是CDlgWindow的非静态成员函数,这类函数在调用时必须绑定类实例(隐含this指针作为第一个参数),它的实际类型是bool (CDlgWindow::*)(const int&),和remove_if要求的谓词签名不匹配。 - 编译器提示的
use '&CDlgWindow::single_digit' to create a pointer to member只是说明成员函数指针的正确书写格式,不代表加了取地址符就能直接使用——拿到成员函数指针后依然需要绑定对应的类实例,才能正常调用。
可行解决方案
方案1:使用C++11 Lambda表达式(最简洁推荐)
Lambda可以直接捕获当前上下文的this指针,完美匹配谓词签名,不需要额外修改现有代码结构:
// 替换原来的numList.remove_if(single_digit);即可 numList.remove_if([this](const int& value) { return value >= _days; // 也可以写为return single_digit(value);复用原有成员函数逻辑 });
这种写法不需要额外定义辅助类,逻辑直观,是当前C++开发中的主流实现方式。
方案2:自定义仿函数(Functor)实现
对应你正在学习的仿函数概念,本质是定义一个重载了()运算符的类型,把判断需要的上下文参数(这里是阈值_days)存在实例内部:
// 可以定义在cpp文件的匿名命名空间中,或者类定义前 struct DigitCheckPredicate { int threshold; // 构造时传入判断需要的阈值 DigitCheckPredicate(int days) : threshold(days) {} // 重载()运算符,让实例可以像函数一样被调用 bool operator()(const int& value) { return value >= threshold; } }; // 调用处代码 numList.remove_if(DigitCheckPredicate(_days));
仿函数是C++11普及前STL算法最常用的谓词实现方式,优点是逻辑封装清晰,可复用性强。
方案3:绑定成员函数指针(旧标准兼容写法)
如果需要兼容不支持C++11的旧编译环境,可以用std::bind把成员函数和当前实例指针绑定,生成符合要求的可调用对象,需要引入<functional>头文件:
#include <functional> // 调用处代码 numList.remove_if(std::bind(&CDlgWindow::single_digit, this, std::placeholders::_1));
其中std::placeholders::_1是占位符,对应remove_if遍历列表时传入的元素参数。
内容的提问来源于stack exchange,提问作者SCodesR
相关产品推荐
相关产品推荐

