Ste*_*mer 87 lambda overloading c++11
在下面的代码中,第一次调用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)
}
Run Code Online (Sandbox Code Playgroud)
+这里的符号是什么?
dyp*_*dyp 90
该+表达式中的+[](){}是一元+运算符.它在[expr.unary.op]/7中定义如下:
一元运算
+符的操作数应具有算术,无范围枚举或指针类型,结果是参数的值.
lambda不是算术类型等,但它可以转换:
[expr.prim.lambda]/3
的类型的λ-表达 [...]是一个独特的,无名不愈合类类型-称为闭合类型 -其特性如下所述.
[expr.prim.lambda]/6
用于闭合型λ-表达无λ-捕获具有
public非virtual非explicitconst转换功能函数指针具有相同的参数和返回类型为闭合类型的函数调用操作.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.
因此,一元+强制转换为函数指针类型,这是针对此lambda的void (*)().因此,表达式的类型+[](){}是此函数指针类型void (*)().
第二个重载void foo(void (*f)())在重载分辨率的排名中变为精确匹配,因此明确地选择(因为第一个重载不是精确匹配).
拉姆达[](){}可以转换为std::function<void()>通过的非显式模板构造函数std::function,它接受的任何类型的满足Callable和CopyConstructible要求.
lambda也可以void (*)()通过闭包类型的转换函数转换为(见上文).
两者都是用户定义的转换序列,并且具有相同的等级.这就是为什么由于模糊性导致第一个例子中的重载决策失败的原因.
根据Cassio Neri的说法,在DanielKrügler的论证支持下,这种一元化的+技巧应该是指定的行为,即你可以依赖它(参见评论中的讨论).
如果你想避免歧义,我建议对函数指针类型使用显式强制转换:你不需要询问SO是什么以及为什么它起作用;)
| 归档时间: |
|
| 查看次数: |
6710 次 |
| 最近记录: |