Descubrí que los lvaluecierres lambda siempre se pueden pasar como rvalueparámetros de función.
Vea la siguiente demostración simple.
#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;
}
El caso 2 es el comportamiento estándar (acabo de utilizar un std::functionpara fines de demostración, pero cualquier otro tipo se comportaría igual).
¿Cómo y por qué funciona el caso 1? ¿Cuál es el estado de fn1cierre después de que la función regresó?
std::functionpueden deducirse los argumentos de plantilla de una lambda?". Su programa no intenta deducir los argumentos de la plantilla std::function, por lo que no hay problema con la conversión implícita.
std::functiontiene un constructor no explícito que acepta cierres lambda, por lo que hay una conversión implícita. Pero en las circunstancias de la pregunta vinculada, la instanciación de plantilla de std::functionno se puede inferir del tipo lambda. (Por ejemplo, std::function<void()>se puede construir [](){return 5;}a pesar de que tiene un tipo de retorno no nulo.
fn1se convierte implícitamente a unastd::functionenfoo(fn1). Esa función temporal es entonces un valor r.