为什么std::function未进行预期的参数类型检查?
关于std::function参数类型不匹配仍可正常编译的问题解答
结论
这个行为是完全符合C++标准的预期设计,不属于编译器bug。
核心原理
std::function的构造要求不是「可调用对象的签名和std::function的签名完全一致」,而是「该可调用对象可以使用std::function声明的参数列表正常调用,且返回值可转换为std::function声明的返回类型」。
简单来说,std::function的参数规则允许合法的隐式类型转换,只要你实际调用std::function时传入的参数,能正常传给内部存储的可调用对象,构造就是合法的,这是std::function类型擦除设计为了提升灵活性做的特意设计。
示例代码逐条解释
以下基于提问中的测试代码逐行验证合法性,其中CallbackType定义为std::function<void(bool&)>,代表调用该std::function时需要传入一个bool类型的左值引用:
CallbackType cb1 = [](bool b) { b = !b; };:调用cb1时传入的bool&可以直接拷贝赋值给值类型形参b,属于合法隐式转换,编译通过。CallbackType cb2 = toggleOk;:签名完全匹配,合法。CallbackType cb3 = toggleBroken;:和cb1逻辑一致,传入的bool&可以拷贝给值类型形参b,合法。CallbackType cb4 = toggleInt;:bool类型可以隐式转换为int,调用时传入的bool&指向的布尔值可以正常转为int传给形参i,合法。WrongCallbackType cb5 = toggleBroken;:签名完全匹配WrongCallbackType的void(bool)声明,合法。CallbackType cb6 = cb5;:WrongCallbackType实例本身是可调用对象,用bool&作为参数调用它完全合法(引用自动转为值),因此可以构造CallbackType,合法。CallbackType cb7 = tooManyParams;:该函数需要2个参数,而CallbackType调用时只会传入1个参数,无法完成调用,因此编译报错。
为什么没有触发警告
上述所有通过编译的场景都是C++标准明确允许的合法用法,不属于错误或风险写法,因此编译器默认不会触发警告。
内容的提问来源于stack exchange,提问作者doomista
相关产品推荐
相关产品推荐

