std::函数与自动调用不同的重载

std::function vs auto call to different overload

本文关键字:重载 调用 函数 std      更新时间:2023-10-16

我有以下一段代码:

#include <iostream>
#include <functional>
void f(const std::function<void()>&)  
{  
std::cout << "In f(const std::function<void()>&)." << std::endl;  
}  
void f(std::function<void()>&&)
{  
std::cout << "In f(std::function<void()>&&)." << std::endl;  
}  
int main()  
{  
auto func = []() { std ::cout << "funcn"; };
f(func); // calls void f(std::function<void()>&&)
/*const*/ std::function<void()> func2 = []() { std ::cout << "funcn"; };
f(func2); // calls void f(const std::function<void()>&)
f([]() { std ::cout << "funcn"; }); // calls void f(std::function<void()>&&)
return 0;
} 

我想知道为什么第一次调用f(当我使用auto和 lambda 函数时)调用void f(std::function<void()>&&)重载而不是void f(const std::function<void()>&),而是在我将变量声明为 (const)std::function<void()>时,第二次调用f调用

对于第一种情况,即使用autofunc的类型是唯一的lambda闭包类型,它不是std::function<void()>,但可以隐式转换为std::function

std::function 的实例可以存储、复制和调用任何可调用目标 - 函数、lambda 表达式、绑定表达式或其他函数对象,以及指向成员函数的指针和指向数据成员的指针。

转换后,我们将得到一个类型std::function<void()>的右值,并且在重载解析中将右值引用绑定到右值比将左值引用绑定到右值更好,然后调用第二个重载。

3) 标准转换序列

S1 优于标准转换序列 S2,如果

c) 或者,如果不是这样,S1 和 S2 都绑定到引用参数到引用限定成员函数的隐式对象参数以外的内容,并且 S1 将右值引用绑定到右值,而 S2 将左值引用绑定到右值

对于第二种情况,func2被声明为std::function<void()>的确切类型,那么对于f(func2);则不需要转换。由于命名变量func2是不能绑定到 rvalue-reference 的左值,因此将调用第一个重载。

如果右值参数对应于

非常量左值引用参数,或者左值参数对应于右值引用参数,则该函数不可行。