以下是我的解决方案,可以将lambda(以及任何函数对象 - 即任何可以调用
operator()
的东西)包装成委托。它有一些限制 - 具体来说,它不支持具有跟踪引用参数的委托(C++/CLI 中的
%
,C# 中的
ref
/
out
); 并且它对委托可以接受的参数数量有一个上限(因为 VC++2010 不支持可变参数模板) - 尽管代码可以轻松地调整以支持多达您需要的数量。
#pragma once
#include <new>
#include <type_traits>
namespace detail
; };
template <class D>
struct illegal_delegate_type
;
struct anything
;
public:
template<class D>
static decltype(static_cast<D^>(nullptr)()) dummy(int[2]);
template<class D>
static decltype(static_cast<D^>(nullptr)(anything(), anything())) dummy(int
示例用法:
Func<int, String^, int>^ f2 = make_delegate([&](int x, String^ y) -> int {
Console::WriteLine("Func {0} {1}", x, y);
return 2;
});
虽然从技术上讲,这样做可以实现您的要求,但由于C++0x lambdas被扩展为普通类而不是
ref
或
value
类,因此其实际应用受到了一定的限制。在C++/CLI中,由于普通类不能包含托管类型(即没有对象句柄类型的成员、没有跟踪引用类型的成员和没有
value class
类型的成员),这意味着lambda也不能捕获任何这些类型的变量。我不知道有什么解决方法可以解决跟踪引用类型的问题。对于
value class
,您可以取一个非托管指针(如果需要,可以使用
pin_ptr
),并捕获它。
对于对象句柄,您可以将它们存储在gcroot<T>
中,然后捕获它,但会有严重的性能影响-在我的测试中,通过gcroot<T>
访问成员大约比使用普通对象句柄慢40倍。对于单个调用来说,绝对值并不多,但对于在循环中重复调用的东西-比如大多数LINQ算法-这将是致命的。但请注意,这仅适用于需要在lambda中捕获句柄的情况!如果您只是在内联中使用它来编写谓词或更新计数器,那么它将正常工作。