简体   繁体   中英

std::function vs auto call to different overload

I have the following piece of code:

#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;
} 

I would like to know why the first call to f (when I use auto and the lambda function) calls the void f(std::function<void()>&&) overload and not the void f(const std::function<void()>&) , which is instead called by the second call to f when I declare the variable as a ( const ) std::function<void()> .

For the 1st case, ie with the usage of auto , the type of func is a unique lambda closure type, which is not of std::function<void()> , but could implicitly convert to std::function .

Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

After the conversion we'll get an rvalue of type std::function<void()> , and binding rvalue-reference to rvalue is better match than binding lvalue-reference to rvalue in overload resolution , then the 2nd overload is invoked.

3) A standard conversion sequence S1 is better than a standard conversion sequence S2 if

c) or, if not that, both S1 and S2 are binding to a reference parameter to something other than the implicit object parameter of a ref-qualified member function, and S1 binds an rvalue reference to an rvalue while S2 binds an lvalue reference to an rvalue

For the 2nd case, func2 is declared as the exact type of std::function<void()> , then for f(func2); no conversion is required. As a named variable func2 is an lvalue, which can't be bound to rvalue-reference, then the 1st overload is invoked.

if an rvalue argument corresponds to non-const lvalue reference parameter or an lvalue argument corresponds to rvalue reference parameter, the function is not viable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM