无法将初始化列表转为std::map:Lambda与成员函数指针适配问题求助
C++ Lambda初始化成员函数指针map编译错误问题
问题描述
在类A的头文件中定义了存储成员函数指针的std::map,尝试用带[this]捕获的Lambda初始化该map时,出现编译错误,提示无法将初始化列表转换为std::map<const std::string, FUNCPTR>,参考同类问题解答后仍未解决。
头文件代码
class A { private: struct ARGS { size_t length{0}; std::string str{""}; }; typedef int(A::*FUNCPTR)(const std::vector<ARGS> &); std::map<const std::string, FUNCPTR> func_map { {"PRINT_HW", [this](const std::vector<ARGS> args){ validate(args, 0); A::cmd_phw(); } }, {"PRINT_NAME", [this](const std::vector<ARGS> args){ validate(args, 1); A::cmd_pn(args[0]); } }, {"PRINT_NAME_SURNAME", [this](const std::vector<ARGS> args){ validate(args, 2); A::cmd_pns(args[0], args[1]); } }, }; // 现有命令的函数声明 int cmd_phw(); int cmd_pn(ARGS args1); int cmd_pns(ARGS args1, ARGS args2); static void validate(const std::vector<ARGS> &args, size_t needed) { if (args.size() != needed) { throw std::invalid_argument("参数数量错误!"); } } public: A(); // 类构造函数声明 int call_print(const std::string& str, const std::vector<ARGS> &args); };
.cpp文件中call_print实现
int A::call_print(const std::string& str, const std::vector<ARGS> &args) { FUNCPTR fp = func_map[str]; int r = (this->*fp)(args); return r; }
错误信息
无法将‘{{"PRINT_HW", <lambda闭包对象>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}, {"PRINT_NAME", <lambda闭包对象>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}, {"PRINT_NAME_SURNAME", <lambda闭包对象>A::<lambda(std::vector<A::ARGS>)>{((A*)this)}}}’从‘<大括号包围的初始化列表>’转换为‘std::map<const std::__cxx11::basic_string<char>, int (A::*)(const std::vector<A::ARGS>&)>’
原因及解决方案
核心原因
捕获了this的Lambda不能隐式转换为成员函数指针。只有无捕获的Lambda才能转换为普通函数指针,而带this捕获的Lambda本质是带状态的闭包对象,与成员函数指针的类型完全不匹配。
解决方案1:改用std::function替代成员函数指针
将成员函数指针类型替换为std::function,它可以直接存储带捕获的Lambda:
// 修改FUNCPTR定义 typedef std::function<int(const std::vector<ARGS>&)> FUNCPTR; std::map<const std::string, FUNCPTR> func_map { {"PRINT_HW", [this](const std::vector<ARGS>& args){ validate(args, 0); this->cmd_phw(); } }, {"PRINT_NAME", [this](const std::vector<ARGS>& args){ validate(args, 1); this->cmd_pn(args[0]); } }, {"PRINT_NAME_SURNAME", [this](const std::vector<ARGS>& args){ validate(args, 2); this->cmd_pns(args[0], args[1]); } }, };
同时调整call_print的调用逻辑:
int A::call_print(const std::string& str, const std::vector<ARGS> &args) { FUNCPTR fp = func_map[str]; int r = fp(args); return r; }
解决方案2:封装适配成员函数
如果坚持使用成员函数指针,可将Lambda逻辑封装成适配成员函数,直接用成员函数指针初始化map:
// 新增适配成员函数 int cmd_phw_adapter(const std::vector<ARGS>& args) { validate(args, 0); return cmd_phw(); } int cmd_pn_adapter(const std::vector<ARGS>& args) { validate(args, 1); return cmd_pn(args[0]); } int cmd_pns_adapter(const std::vector<ARGS>& args) { validate(args, 2); return cmd_pns(args[0], args[1]); } // 初始化map std::map<const std::string, FUNCPTR> func_map { {"PRINT_HW", &A::cmd_phw_adapter}, {"PRINT_NAME", &A::cmd_pn_adapter}, {"PRINT_NAME_SURNAME", &A::cmd_pns_adapter}, };
内容的提问来源于stack exchange,提问作者rere
相关产品推荐
相关产品推荐

