functional c++ c++11 lambda rvalue-reference

functional - C++ 11 lambda se puede asignar a std:: function con firma incorrecta



lambda c (2)

Lo siguiente compila y ejecuta (bajo Apple LLVM versión 6.1.0 y Visual C ++ 2015):

#include <functional> #include <iostream> struct s { int x; }; int main(int argc, char **argv) { std::function<void (s &&)> f = [](const s &p) { std::cout << p.x; }; f(s {1}); return 0; }

¿Por qué la asignación std::function<void (s &&)> f = [](const s &p) { std::cout << px; }; std::function<void (s &&)> f = [](const s &p) { std::cout << px; }; generar un error? Una función que acepta una referencia de valor no debe tener la misma firma que una función que acepta una referencia de valor constante, ¿debería? Eliminar la const de la declaración de la lambda genera un error como se esperaba.


Para ampliar el comentario y la respuesta existentes:

El punto de std::function<R(A...)> es que puede envolver cualquier función o funtor que pueda llamarse con A... y tener el resultado almacenado en una R

Así por ejemplo,

std::function<int(int)> f = [](long l) { return l; };

es sólo peachy.

Entonces, ¿qué tiene que preguntarse cuando vea algo como esto: si tiene un lambda tomando const T & , y tiene una expresión de tipo T && (o, más exactamente, tiene un xvalor de tipo T ), puede ¿Usar esa expresión para llamar a la lambda?

Sí tu puedes.

Y si puedes, entonces se supone que la std::function es capaz de almacenar ese functor. Ese es el punto principal de la std::function .


Por favor, tome esto con un grano de sal. Esto es lo que entiendo, pero no estoy seguro.

Considere el siguiente resultado:

int main(int argc, char **argv) { std::cout << std::is_convertible<s &&, s&>::value << std::endl; //false std::cout << std::is_convertible<s &&, const s&>::value << std::endl; //true std::cout << std::is_convertible<const s &, s&&>::value << std::endl; //false return 0; }

Esto muestra que es posible convertir un s && en un const s& . Esta es la razón por la cual la asignación de la std::function está bien.

Eliminar la const de la declaración de la lambda genera un error como se esperaba.

De hecho, esto se debe a que (como se muestra anteriormente), la conversión de un s && a un s & no es posible.

De la misma manera, intentando lo contrario.

std::function<void (const s &)> f = [](s &&p) { std::cout << px; }; fallaría porque no es posible convertir una const s& a s && .