为此,我编写了 Lamda2Delegate 结构。实际上,它将 c++11 lambda 转换为任何 .net 委托。
使用示例:
Thread^ TestLambaWrapper()
{
gcroot<String ^> str = "Testext";
int i = 12345;
Thread^ newThread = gcnew Thread(
Lambda2Delegate<ParameterizedThreadStart>() = [&, str](Object ^ str2)
{
Sleep(2000);
Console::WriteLine("Thread output = {0} {1} {2}", str, i, str2);
}
);
newThread->Start("Nahnah");
return newThread;
}
对于您的情况:
gcroot<A^> a = gcnew A();
Func<A^> ^ aFunc = Lambda2Delegate<>() = [a](){ return (A^)a; };
auto a2 = aFunc();
要捕获托管类,您需要使用 gcroot 包装它们,并按值显式捕获。
和 Lambda2Delegate.h 本身
#pragma once
#ifdef _MANAGED
struct AutoDetectDelegateType {};
template<typename TDelegate, typename TLambda, typename TRet, typename ...TParams>
ref class LambdaHolder;
template<typename TDelegate, typename TLambda, typename TRet, typename ...TParams>
ref class LambdaHolder
{
public:
inline LambdaHolder(const TLambda % func) { m_func = new TLambda(func); }
!LambdaHolder() { delete m_func; }
~LambdaHolder() { !LambdaHolder(); }
public:
TRet Callback(TParams... params) { return (*m_func)(params...); }
operator TDelegate ^ () { return gcnew TDelegate(this, &LambdaHolder::Callback); }
private:
TLambda * m_func;
};
template<typename TLambda, typename TRet, typename ...TParams>
ref class LambdaHolder<AutoDetectDelegateType, TLambda, TRet, TParams...>
{
public:
inline LambdaHolder(const TLambda % func) { m_func = new TLambda(func); }
!LambdaHolder() { delete m_func; }
~LambdaHolder() { !LambdaHolder(); }
public:
TRet Callback(TParams... params) { return (*m_func)(params...); }
template<typename TDelegate>
operator TDelegate ^ () { return gcnew TDelegate(this, &LambdaHolder::Callback); }
private:
TLambda * m_func;
};
template <typename TDelegate, typename TLambda>
struct get_labmda_holder : public get_labmda_holder < TDelegate, decltype(&TLambda::operator()) > {};
template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
struct get_labmda_holder < TDelegate, TRet(__clrcall TLambda::*)(TParams...) const >
{
typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
};
template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
struct get_labmda_holder < TDelegate, TRet(__clrcall TLambda::*)(TParams...) >
{
typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
};
template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
struct get_labmda_holder < TDelegate, TRet(__thiscall TLambda::*)(TParams...) const >
{
typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
};
template <typename TDelegate, typename TLambda, typename TRet, typename... TParams>
struct get_labmda_holder < TDelegate, TRet(__thiscall TLambda::*)(TParams...)>
{
typedef LambdaHolder<TDelegate, TLambda, TRet, TParams...> TLambdaHolder;
};
template<typename TDelegate = AutoDetectDelegateType>
struct Lambda2Delegate
{
template<typename TLambda>
typename get_labmda_holder<TDelegate, TLambda>::TLambdaHolder ^ operator = (const TLambda % func)
{
return gcnew get_labmda_holder<TDelegate, TLambda>::TLambdaHolder(func);
}
};
#endif
更新:不可能在托管成员函数中声明 c++ lambda 函数,但有解决方法 - 使用静态成员函数:
ref class S
{
public:
int F(System::String ^ str)
{
return F(this, str);
}
private:
//static function declaring c++ lambda
static int F(S ^ pThis, System::String ^ str)
{
gcroot<System::String ^> localStr = "local string";
System::Func<System::String ^, int> ^ func = Lambda2Delegate<>() = [=](System::String ^ str)
{
System::Console::WriteLine(str);
System::Console::WriteLine(localStr);
return str->Length;
};
return func(str);
}
};