如何使用Lambda替代std::bind绑定成员函数以符合clang-tidy要求
用Lambda替代std::bind实现成员函数绑定的解决方案
我完全懂你的困扰——把std::bind换成Lambda来绑定成员函数到上下文对象,确实得搞清楚捕获和调用的正确姿势,咱们直接上手改你的代码,一步步说清楚。
首先,先看修改后的完整代码,和原来的功能完全一致,但用了Lambda替代std::bind:
template<typename Foo> class Bar { public: template<class THandlerObj> Bar(void (THandlerObj::*pCmdHandler)(const Foo&), THandlerObj* pCmdHandlerContext) : m_cmdHandlerFunc([pCmdHandlerContext, pCmdHandler](const Foo& foo) { // 调用上下文对象的目标成员函数 (pCmdHandlerContext->*pCmdHandler)(foo); }) { } private: std::function<void(const Foo&)> m_cmdHandlerFunc; };
关键细节解释
- Lambda捕获列表:我们需要把
pCmdHandlerContext(上下文对象的指针)和pCmdHandler(成员函数指针)捕获到Lambda里。这里用值捕获就足够了,因为它们都是指针类型,拷贝的成本极低,也不会有生命周期问题(只要你保证pCmdHandlerContext在m_cmdHandlerFunc的生命周期内有效,这一点和原来用std::bind的要求是一样的)。 - 成员函数调用语法:
(pCmdHandlerContext->*pCmdHandler)(foo)这里的括号不能省略!因为成员函数指针的优先级比->*运算符低,必须用括号明确先把对象指针和成员函数指针绑定,再调用这个组合后的函数并传入参数。 - Lambda的参数匹配:Lambda的参数
const Foo& foo和原来std::bind生成的函数签名完全一致,这样才能正确赋值给std::function<void(const Foo&)>类型的成员变量。
额外优化(C++14及以上)
如果你的项目用的是C++14或更高版本,可以用auto自动推导参数类型,让代码更简洁:
m_cmdHandlerFunc([pCmdHandlerContext, pCmdHandler](const auto& foo) { (pCmdHandlerContext->*pCmdHandler)(foo); })
这样即使后续Foo的类型有调整,Lambda的参数也能自动适配,不用手动修改。
另外,如果想避免空指针调用的风险,可以在构造函数里加个断言(可选):
#include <cassert> // 在构造函数初始化列表之前添加 assert(pCmdHandlerContext != nullptr);
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

