Resolving ambiguous overload on function pointer and std::function for a lambda using + (unary plus)(使用+(一元加号)解决lambda的函数指针和std::function上的多义性重载)
问题描述
在下面的代码中,对foo的第一个调用不明确,因此无法编译。
第二个在lambda之前添加了+,解析为函数指针重载。
#include <functional>
void foo(std::function<void()> f) { f(); }
void foo(void (*f)()) { f(); }
int main ()
{
foo( [](){} ); // ambiguous
foo( +[](){} ); // not ambiguous (calls the function pointer overload)
}
+符号在这里做什么?
推荐答案
表达式+[](){}中的+是一元运算符。它的定义如下所示
[Expr.unary.op]/7:
一元
+运算符的操作数应为算术、无作用域枚举或指针类型,结果为参数的值。
lambda不是算术类型等,但可以转换:
[expr.prim.lambda]/3
lambda表达式[.]的类型是一种唯一的、未命名的非联合类类型,称为闭包类型,其属性如下所述。
[expr.prim.lambda]/6
因此,一元lambda-expression没有lambda-capture的闭包类型有一个
public非virtualconst转换函数,该函数指向与闭包类型的函数调用运算符具有相同参数和返回类型的函数指针。此转换函数返回的值应为调用时与调用闭包类型的函数调用运算符具有相同效果的函数的地址。
+强制转换为函数指针类型,该类型适用于这个lambdavoid (*)()。因此,表达式+[](){}的类型是该函数指针类型void (*)()。
第二个重载void foo(void (*f)())在重载解析排名中变为完全匹配,因此被毫不含糊地选择(因为第一个重载不是完全匹配)。
可以通过std::function的非显式模板ctor将lambda[](){}转换为std::function<void()>,该ctor采用满足Callable和CopyConstructible要求的任何类型。
也可以通过闭包类型的转换函数将lambda转换为void (*)()(如上所述)。
根据Cassio Neri的说法,并得到Daniel Krügler的支持,这个一元的+技巧应该是指定的行为,也就是说,您可以依赖它(参见评论中的讨论)。
不过,如果您想避免歧义,我建议您使用显式转换到函数指针类型:您不需要问它做了什么,为什么它会工作;)
这篇关于使用+(一元加号)解决lambda的函数指针和std::function上的多义性重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用+(一元加号)解决lambda的函数指针和std::function上的多义性重载
基础教程推荐
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 常量变量在标题中不起作用 2021-01-01
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 如何通过C程序打开命令提示符Cmd 2022-12-09
