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

C++ std::函数与自动调用不同重载,c++,c++11,lambda,overloading,auto,C++,C++11,Lambda,Overloading,Auto,我有以下代码: #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()>&a

我有以下代码:

#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 << "func\n"; };
    f(func); // calls void f(std::function<void()>&&)

    /*const*/ std::function<void()> func2 = []() { std ::cout << "func\n"; };
    f(func2); // calls void f(const std::function<void()>&)

    f([]() { std ::cout << "func\n"; }); // calls void f(std::function<void()>&&)

    return 0;
} 
#包括
#包括
void f(const std::function&)
{  

std::cout对于第一种情况,即使用
auto
func
的类型是唯一的lambda闭包类型,它不是
std::function
,但可以隐式转换为

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

转换之后,我们将得到一个类型为
std::function
的右值,并且将右值引用绑定到右值比将左值引用绑定到右值更匹配,然后调用第二个重载

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

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

对于第二种情况,
func2
被声明为
std::function
的确切类型,然后对于
f(func2);
不需要转换。由于命名变量
func2
是一个左值,不能绑定到右值引用,因此调用第一个重载

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


lambda的类型不是
std::function
,因此第一个调用会触发隐式转换。这是您误解的根源吗?@BaummitAugen是的,隐式转换是如何定义的,为什么它更喜欢右值引用重载?谢谢您的回答。我知道使用
auto
有几个优点在性能方面,与
std::function
相比,在声明lambda时,我想知道如果需要将lambda传递给接受
std::function
的方法,那么隐式转换的代价是什么,在这种情况下,在第一个pl中将变量声明为
std::function
是否更好ace.@Nick在大多数情况下不需要
std::function
;像
template void f(FUNC&&FUNC)
这样的函数模板将为您完成这项工作。@songyuanyao要求您在头文件中公开实现,这是一项不小的成本。@Nick是否将其存储在std::function对象中取决于(a)您是否会多次通过引用调用std::function,以及(b)lambda对象有多大(即,std::function是否需要执行堆分配来存储它?)。您的示例中有未捕获的lambda,它们足够小,无关紧要。