funciones c++ c++11 lambda stdbind

c++ - funciones - std:: async usando una referencia rvalue vinculada a un lambda



funciones lambda c++ (1)

Estoy intentando vincular una referencia rvalue a un lambda usando std::bind , pero tengo problemas cuando lo incluyo en una llamada std::async : ( fuente )

auto lambda = [] (std::string&& message) { std::cout << message << std::endl; }; auto bound = std::bind(lambda, std::string{"hello world"}); auto future = std::async(bound); // Compiler error here future.get()

Esto genera un error del compilador que no estoy seguro de cómo interpretar:

error: ningún tipo llamado ''tipo'' en ''clase std :: result_of (std :: basic_string)> & ()>''

¿Que está pasando aqui? Curiosamente, una ligera modificación se compila y funciona como se esperaba. Si cambio std::string{"hello world"} a un literal c-string, todo funciona bien: ( fuente )

auto lambda = [] (std::string&& message) { std::cout << message << std::endl; }; auto bound = std::bind(lambda, "hello world"); auto future = std::async(bound); future.get(); // Prints "hello world" as expected

¿Por qué funciona esto pero no es el primer ejemplo?


std::bind va a hacer una copia del argumento std::string y pasarlo a la lambda. Pero eso no se puede compilar porque la lambda requiere un argumento rvalue, mientras que lo que pasa es un lvalue. Puedes hacer que esto funcione si obtienes bind para move el argumento, pero esto requiere un casting extremadamente desagradable para la desambiguación (porque std::move es una función sobrecargada).

auto bound = std::bind(lambda, std::bind(static_cast<std::string&&(*)(std::string&)>(std::move), std::string{"hello world"}));

Demo en vivo

Por supuesto, podría escribir su propia versión del move que no esté sobrecargada, y evitar ese lanzamiento.

El segundo caso funciona porque cuando bind pasa el char const * al lambda, se crea rvalue std::string temporary de forma implícita.

Para explicar el mensaje de error que está viendo, en algún lugar dentro de las entrañas de std::async , std::result_of se invoca para determinar el tipo de retorno de la expresión de llamada a la función. Sin embargo, debido a que la expresión de llamada no es válida debido a los motivos explicados anteriormente, result_of está siendo SFINAE (esto es un cambio de C ++ 14). De ahí el error error: no type named ''type'' in ''class std::result_of<...>'' .