c++ - 使用 +(一元加)解决 lambda 的函数指针和 std::function 上的不明确重载

标签 c++ c++11 lambda overloading

在以下代码中,对 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)
}

+ 符号在这里做什么?

最佳答案

+在表达式 +[](){} 中是一元 +运算符(operator)。它的定义如下 [expr.unary.op]/7:

The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument.

lambda 不是算术类型等,但可以转换:

[expr.prim.lambda]/3

The type of the lambda-expression [...] is a unique, unnamed non-union class type — called the closure type — whose properties are described below.

[expr.prim.lambda]/6

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type's function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

因此,一元 +强制转换为函数指针类型,这是针对此 lambda void (*)() 。因此,表达式 +[](){} 的类型这个函数指针类型是void (*)() .

第二次过载void foo(void (*f)())在重载解析的排名中成为精确匹配,因此被明确选择(因为第一个重载不是精确匹配)。

<小时/>

lambda [](){}可以转换为std::function<void()>通过std::function的非显式模板ctor ,它采用满足 Callable 的任何类型和CopyConstructible要求。

lambda 也可以转换为 void (*)()通过闭包类型的转换函数(见上文)。

两者都是用户定义的转换序列,并且具有相同的等级。这就是为什么重载解析在第一个示例中由于不明确而失败的原因。

<小时/>

根据 Cassio Neri 的说法,并得到 Daniel Krügler 的论证支持,这个一元 +技巧应该是指定的行为,即您可以依赖它(请参阅评论中的讨论)。

不过,如果您想避免歧义,我建议您使用显式转换为函数指针类型:您不需要询问它的作用和原因;)

关于c++ - 使用 +(一元加)解决 lambda 的函数指针和 std::function 上的不明确重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17822131/

相关文章:

c++ - 检测程序集是否可用

c++ - 仅当某个模板具有给定类的专门化时,如何 std::enable_if

c++ - 我们可以使用 lambda 创建 unique_ptr 吗?

c++ - 从派生类中删除虚函数

C# 传递强类型属性名称列表

java - 用 java8 lambda 函数替换所有

c++ - 渲染数学公式 : algorithms

c++ - 区分带小数位的数字(double 类型)和不带小数位的数字 - C++

c++ - 在这种特殊情况下,您会推荐使用程序集来访问参数吗?

c++ - 使用 std::get_time 转换 ANSI C 的 asctime() 格式