传递std::function作为参数遇语法错误,需非模板方案解决
问题解决:std::function参数传递与std::map存储的语法错误
错误详情及原因
ERROR#1:非静态成员函数传递错误
错误信息(翻译后):
message.cc:37:44: 错误:无效使用非静态成员函数‘void message::print(std::string)’ registerHandler(msg1.id_, msg1, message::print);
原因:message::print是非静态成员函数,它的真实签名是void(message::*)(std::string),和你声明的std::function<void(string)>类型不匹配。非静态成员函数必须依附类的实例才能调用,不能直接把它当作普通函数指针传递。
ERROR#2:std::bind用法错误+类型不匹配
错误信息(翻译后):
message.cc: 在函数‘void registerHandler(int, message&, std::function<void(std::basic_string<char>)>&)’中: message.cc:24:42: 错误:没有匹配的函数调用‘std::map<int, std::function<void(std::basic_string<char>)> >::insert(<大括号包裹的初始化列表>)’ functionMap.insert({id, messageHandler}); ^
原因:
- 你的
bind用法完全错误:绑定成员函数时,第一个参数必须是成员函数指针,第二个是对象的指针或引用,最后是参数占位符,而不是绑定func本身。 registerHandler的第三个参数是std::function<void(string)>&左值引用,但你无法直接将成员函数指针转换为这个类型的左值,导致后续绑定后的类型和std::map存储的类型不匹配,触发insert错误。
修正方案(满足非模板registerHandler需求)
直接让registerHandler接受message类的成员函数指针,内部完成绑定后存入map:
#include <map> #include <functional> #include <iostream> using namespace std; class message { public: void print(string command) { cout << "message id: " << id_ << " content: " << command << std::endl; } int id_ = 0; }; std::map<int, function<void(string)>> functionMap; // 第三个参数改为message类的成员函数指针 void registerHandler(int id, message& msg, void (message::*func)(string)) { // 正确绑定成员函数与对象实例 auto messageHandler = bind(func, &msg, placeholders::_1); functionMap.insert({id, messageHandler}); } int main() { message msg1; msg1.id_ = 5000; // 传递成员函数指针时必须加& registerHandler(msg1.id_, msg1, &message::print); // 遍历map调用回调(简化写法) for (const auto& entry : functionMap) { entry.second("Junk Payload"); } }
扩展方案(支持任意可调用对象)
如果需要支持更多类型的回调(比如普通函数、lambda),可以把registerHandler的第三个参数改成std::function<void(string)>值传递,调用时提前完成绑定:
// 修改后的registerHandler void registerHandler(int id, std::function<void(string)> func) { functionMap.insert({id, func}); } // main中的调用方式 int main() { message msg1; msg1.id_ = 5000; // 提前绑定成员函数与实例 registerHandler(msg1.id_, bind(&message::print, &msg1, placeholders::_1)); // 也可以直接传lambda registerHandler(1001, [&msg1](string cmd) { msg1.print(cmd); }); for (const auto& entry : functionMap) { entry.second("Junk Payload"); } }
内容的提问来源于stack exchange,提问作者tadpole
相关产品推荐
相关产品推荐

