C++17中std::bind生成std::function失败的原因排查
这完全是代码编写错误,和C++11/14/17的特性移除没有任何关系!咱们来拆解一下问题出在哪:
你的TestClass::TestTarget成员函数需要三个参数——除了显式声明的const uint8_t* data和size_t len,还有隐式的this指针。当用std::bind绑定成员函数时,你需要为成员函数的每一个显式参数都提供对应的占位符,而你当前的代码只给了第一个参数的占位符std::placeholders::_1,漏掉了第二个参数的_2。
这就导致std::bind生成的 functor 只能接受1个参数,但Register函数要求的std::function<void(const uint8_t*, size_t)>需要接受2个参数,类型完全不匹配。编译器的静态断言检测到成员函数的参数数量和bind提供的占位符数量不匹配,所以抛出了Wrong number of arguments for pointer-to-member的错误。
只需要补上第二个参数的占位符std::placeholders::_2,让bind生成的 functor 能接收两个参数即可:
void TestRegister() { // 添加第二个参数的占位符_2,匹配TestTarget的len参数 Register( std::bind(&TestClass::TestTarget, this, std::placeholders::_1, std::placeholders::_2) ); }
这段代码在C11到C17下都能正常编译运行,和原lambda版本的行为完全一致。
你的lambda版本显式声明了两个参数(const uint8_t* data, size_t len),并且通过捕获this调用TestTarget(data, len),生成的lambda签名和std::function<void(const uint8_t*, size_t)>完全匹配,自然不会有编译错误。相比std::bind,lambda的参数列表更直观,不容易出现这类占位符遗漏的问题。
内容的提问来源于stack exchange,提问作者Maximilian Gerhardt

