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) !
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.