C ++ 0x Lambda到VS 2010中的函数指针 [英] C++0x Lambda to function pointer in VS 2010

查看:175
本文介绍了C ++ 0x Lambda到VS 2010中的函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用lambda传递代替函数指针,但VS2010似乎不能转换它。我已经尝试使用std ::功能像这样,它崩溃,我不知道如果我这样做正确!

  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\\\
;
};


Concurrency :: CurrentScheduler :: ScheduleTask(f.target< void(void *)>(),0);

getch();
}



我似乎很奇怪,编译器不能将这样的lambda转换为一个简单的函数指针,因为它捕获没有变量 - 也在我不知道可以做什么的情况下。



每个lambda的类型是唯一的吗?所以我可以使用lambdas'类型作为模板参数来创建一个模板函数来生成一个唯一的静态函数,可以被调用而希望优化。



strong> UPDATED



以下似乎有效,但是安全吗?

  #include< windows.h> 
#include< conio.h>

#include< iostream>

#include< concrt.h>


模板< typename签名>
struct Bind
{
静态签名方法;

static void Call(void * parameter)
{
method(parameter);
}
};


模板< typename签名>
签名绑定< Signature> :: method;


模板< typename签名>
void ScheduleTask(签名方法)
{
Bind< Signature> :: method = method;
Concurrency :: CurrentScheduler :: ScheduleTask(& Bind< Signature> :: Call,0);
}


void main()
{
ScheduleTask

[](void *)
{
std :: cout<<Hello;
}
);


ScheduleTask

[](void *)
{
std :: cout< n;
}
);


getch();
}

已重新更新 b

所以有了帮助,我想出了更短的:

 模板< typename签名> 
void(* LambdaBind(Signature))(void *)
{
struct Detail
{
static void Bind(void * parameter)
{
签名方法;

method(parameter);
}
};


return& Detail :: Bind;
}

这可以用来包装没有 void(*)(void *)到等效函数指针。看起来这在VS2010的更高版本中将变得不必要。



那么如何使用闭包来处理lambda?





适用于VS2010中的闭包 - 不知道它是否安全...

 模板< typename签名> 
struct Detail2
{
static std :: function< void(void *)>方法;


static void Bind(void * parameter)
{
method(parameter);
}
};


模板< typename签名>
std :: function< void(void *)> Detail2< Signature> :: method;


模板< typename签名>
void(* LambdaBind2(Signature method))(void *)
{
Detail2< Signature> :: method =
return& Detail2< Signature> :: Bind;
}


解决方案

这个特性的lambda是在VS2010实施它们后添加的,所以它们不存在它。



这是一个可能的通用解决方法,未经测试:

  #include< functional> 
#include< iostream>

命名空间细节
{
//帮助专用化,
//定义转发方法
模板< 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
};

//等等
#undef DEFINE_OPERATOR
}

//封装一个lambda并提供
//一种调用方式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
}

让我知道任何部分是否令人困惑。


I am trying to use a lambda to pass in place of a function pointer but VS2010 can't seem to convert it. I have tried using std::function like this and it crashes and I have no idea if I am doing this right!

#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();
}

It seems strange to me that the compiler can't convert such a lambda to a simple function pointer as it captures no variables - also in the case that it did I wonder what can be done.

Is the type of each lambda unique? So I could hack around with a template function using the lambdas' type as a template argument to generate a unique static function that could be called instead and hopefully optimised out?

UPDATED

The below seems to work but is it safe?

#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();
}

UPDATED AGAIN

So with the help given I have come up with the shorter:

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

            method(parameter);
        }
    };


    return &Detail::Bind;
}

This can be used to wrap a lambda with no closure of void(*)(void*) into the equivalent function pointer. It appears that this will become unnecessary in a later version of VS2010.

So how to get this to work for a lambda with closures?

UPDATED AGAIN!

Works for closures in VS2010 - no idea if it's 'safe' though...

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;
}

解决方案

This feature of lambda's was added after VS2010 implemented them, so they don't exist in it yet.

Here's a possible generic work-around, very untested:

#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();
}

Let me know if any part is confusing.

这篇关于C ++ 0x Lambda到VS 2010中的函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆