Odkryłem, że lvaluezamknięcia lambda zawsze można przekazać jako rvalueparametry funkcji.
Zobacz następującą prostą demonstrację.
#include <iostream>
#include <functional>
using namespace std;
void foo(std::function<void()>&& t)
{
}
int main()
{
// Case 1: passing a `lvalue` closure
auto fn1 = []{};
foo(fn1); // works
// Case 2: passing a `lvalue` function object
std::function<void()> fn2 = []{};
foo(fn2); // compile error
return 0;
}
Przypadek 2 to standardowe zachowanie (właśnie użyłem std::functiondo celów demonstracyjnych, ale każdy inny typ zachowałby się tak samo).
Jak i dlaczego działa przypadek 1? Jaki jest stan fn1zamknięcia po zwróceniu funkcji?
std::functionmożna wywnioskować argumentów z lambda”. Twój program nie próbuje wywnioskować argumentów szablonu std::function, więc nie ma problemu z niejawną konwersją.
std::functionma nieprecyzyjny konstruktor, który akceptuje zamknięcia lambda, więc zachodzi niejawna konwersja. Ale w okolicznościach połączonego pytania std::functionnie można wywnioskować z wystąpienia lambda typu szablonu . (Na przykład std::function<void()>można skonstruować z [](){return 5;}tego, że ma on nieważny typ zwrotu.
fn1domyślnie jest konwertowany nastd::functioninfoo(fn1). Ta tymczasowa funkcja jest wtedy wartością rvalue.