转发lambda转函数指针失败:是编译器Bug还是标准未规定?
这不是标准的问题,而是GCC和Clang还没跟进修复的标准缺陷哦!
先理清楚来龙去脉:
- 你用转发函数模板能拿到左值引用的函数指针,是因为引用折叠规则在起作用:当实例化
f<int&>时,T&&会折叠成int&,刚好匹配目标指针类型。 - 左值泛型lambda能转成函数指针也很直观:它的
operator()模板是template<class T> void operator()(T&) const,实例化T=int后就是void(int&),完美契合目标类型。
那转发泛型lambda为啥不行?按道理它的operator()模板是template<class T> void operator()(T&&) const,当T=int&时,T&&会折叠成int&,实例化后的operator()签名就是void(int&) const,无捕获lambda本来就可以转成对应的普通函数指针,逻辑上完全说得通。
问题出在编译器对lambda转函数指针的推导逻辑上:旧版C++标准的措辞没明确这种场景下要应用转发引用的推导规则(也就是允许T被推导成左值引用类型,触发引用折叠),后来CWG 2442缺陷报告专门明确了这种转换应该和普通模板函数调用的推导一致,允许这种情况。但目前GCC和Clang还没实现这个修复,所以才会报错。
你提到能手动获取&decltype(l)::operator()<int &>这个成员函数指针,也侧面证明了实例化后的operator()确实是void(int&) const——只是编译器自动推导转换时没走这条正确的路径而已。
内容的提问来源于stack exchange,提问作者Quentin
相关产品推荐
相关产品推荐

