visual c++ visual-studio-2010 lambda c++11

c++ - cursor visual basic



C++ 0x Lambda para el puntero de la funciĆ³n en VS 2010 (2)

Estoy tratando de usar una lambda para pasar en lugar de un puntero de función, pero parece que VS2010 no puede convertirlo. He intentado usar std :: function como este y se bloquea y no tengo idea si lo estoy haciendo bien.

#include <windows.h> #include <conio.h> #include <functional> #include <iostream> #include <concrt.h> void main() { std::function<void(void*)> f = [](void*) -> void { std::cout << "Hello/n"; }; Concurrency::CurrentScheduler::ScheduleTask(f.target<void(void*)>(), 0); getch(); }

Me parece extraño que el compilador no pueda convertir dicho lambda en un simple puntero de función, ya que no captura ninguna variable; también en el caso de que lo haga, me pregunto qué se puede hacer.

¿Es el tipo de cada lambda único? Entonces, ¿podría piratear con una función de plantilla usando el tipo lambdas como un argumento de plantilla para generar una función estática única que podría llamarse y optimizarse?

ACTUALIZADO

El siguiente parece funcionar, pero ¿es seguro?

#include <windows.h> #include <conio.h> #include <iostream> #include <concrt.h> template<typename Signature> struct Bind { static Signature method; static void Call(void* parameter) { method(parameter); } }; template<typename Signature> Signature Bind<Signature>::method; template<typename Signature> void ScheduleTask(Signature method) { Bind<Signature>::method = method; Concurrency::CurrentScheduler::ScheduleTask(&Bind<Signature>::Call,0); } void main() { ScheduleTask ( [](void*) { std::cout << "Hello"; } ); ScheduleTask ( [](void*) { std::cout << " there!/n"; } ); getch(); }

ACTUALIZADO OTRA VEZ

Entonces, con la ayuda brindada, he encontrado el más corto:

template<typename Signature> void (*LambdaBind(Signature))(void*) { struct Detail { static void Bind(void* parameter) { Signature method; method(parameter); } }; return &Detail::Bind; }

Esto se puede usar para envolver un lambda sin cierre de void(*)(void*) en el puntero de función equivalente. Parece que esto será innecesario en una versión posterior de VS2010.

Entonces, ¿cómo hacer que esto funcione para una lambda con cierres?

¡ACTUALIZADO OTRA VEZ!

Funciona para cierres en VS2010, sin tener en cuenta si es "seguro" ...

template<typename Signature> struct Detail2 { static std::function<void(void*)> method; static void Bind(void* parameter) { method(parameter); } }; template<typename Signature> std::function<void(void*)> Detail2<Signature>::method; template<typename Signature> void (*LambdaBind2(Signature method))(void*) { Detail2<Signature>::method = method; return &Detail2<Signature>::Bind; }


Si lo que desea es programar los objetos lambdas / function en Concurrency :: CurrentScheduler, puede valer la pena mirar el paquete de muestra ConcRT v0.32 aquí

La estructura task_scheduler puede programar lambdas de forma asíncrona, pero tenga en cuenta que pasar por referencia puede causar problemas (ya que estamos hablando de una programación asincrónica sin unir / esperar, una referencia en la pila puede no ser válida en el momento de la ejecución de la tarea) !


Esta característica de lambda se agregó después de que VS2010 los implementó, por lo que aún no existen.

Aquí hay un posible tratamiento genérico, muy no probado:

#include <functional> #include <iostream> namespace detail { // helper specializations, // define forwarding methods template <typename Lambda, typename Func> struct lambda_wrapper; #define DEFINE_OPERATOR / typedef decltype(&call) function_type; / operator function_type(void) const / { / return &call; / } template <typename Lambda, typename C, typename R> struct lambda_wrapper<Lambda, R (C::*)(void) const> { static R call(void) { Lambda x; return x(); } DEFINE_OPERATOR }; template <typename Lambda, typename C, typename R, typename A0> struct lambda_wrapper<Lambda, R (C::*)(A0) const> { static R call(A0&& p0) { Lambda x; return x(std::forward<A0>(p0)); } DEFINE_OPERATOR }; // and so on #undef DEFINE_OPERATOR } // wraps a lambda and provides // a way to call it statically template <typename Lambda> struct lambda_wrapper : detail::lambda_wrapper<Lambda, decltype(&Lambda::operator())> {}; template <typename Lambda> lambda_wrapper<Lambda> wrap_lambda(const Lambda&) { return lambda_wrapper<Lambda>(); } int main(void) { auto l = [](){ std::cout << "im broked :(" << std::endl; }; std::function<void(void)> f = wrap_lambda(l); f(); }

Avíseme si alguna parte es confusa.