std :: function vs auto调用不同的重载

时间:2018-03-07 09:59:59

标签: 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()>&&)
{  
    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;
} 

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

1 个答案:

答案 0 :(得分:5)

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

  

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

转换后我们会得到一个std::function<void()>类型的右值,并且绑定rvalue-reference到rvalue比绑定lvalue-reference到std::function中的rvalue更好,然后是第二个重载被调用。

  

3)如果

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

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

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

  

如果rvalue参数对应于非const左值引用参数或lvalue参数对应于rvalue引用参数,则该函数不可行。