C++成员函数内使用lambda作为成员函数指针参数是否可行
结论
你当前的用法不可行,不存在能让带捕获lambda直接转换成类成员函数指针的语法。
错误原因
- 你实现的
for_each第二个形参是类C的成员函数指针类型,但lambda表达式本质是编译器生成的匿名类对象,和你传入的C(也就是v_context)没有任何继承或归属关系,根本不可能转换成v_context的成员函数指针。 - 即使是无捕获的lambda,也仅支持隐式转换为同签名的普通函数指针,无法转换为类成员函数指针;你代码里的lambda还捕获了上下文变量(
commandBuffers、inheritanceInfo、pipelines、当前对象的this指针),属于带状态的可调用对象,连普通函数指针都无法转换。
正确实现方案
不要把for_each的可调用参数限制为成员函数指针,改成支持任意可调用对象的泛型版本即可,这种写法也是C++标准库算法(比如std::for_each)通用的实现方式:
class model { static std::vector<model*> models; // ... 其他原有成员 public: // 泛型版本:支持lambda、普通函数、函数对象、std::bind包装的成员函数等所有可调用类型 template <class Func> static void for_each(Func&& func) { for (auto* m : models) { func(m); } } // 可选:保留原有成员函数指针的重载,兼容旧的调用代码 template <class C> static void for_each(C* c, void (C::*f)(model*)) { for (auto* m : models) { (c->*f)(m); } } // ... 其他原有成员 };
修改后调用时不需要手动指定模板参数,编译器会自动推导类型,你原来的调用代码可以简化成:
void v_context::build_cmd() { // ... 原有前置逻辑 auto f1 = [&](model* m) -> void { commandBuffers.push_back(*(m->build_secondary_buffers(inheritanceInfo, pipelines.gltf))); }; model::for_each(f1); // ... 原有后续逻辑 }
如果你坚持要使用原来只接受成员函数指针的for_each版本,就不能使用lambda,必须把lambda里用到的所有上下文变量都存为v_context的成员变量,再单独写一个v_context的成员函数作为参数传入,这种写法灵活性极差,不推荐使用。
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

