A customer wanted to create a Windows Runtime method that accepted a lambda. But lambdas aren’t valid Windows Runtime types.
// C++/WinRT IDL runtimeclass MyClass { template<typename TLambda> void ApplyFilter(TLambda&& filter); // Does not compile } // C++/CX public ref class MyClass { public: template<typename TLambda> void ApplyFilter(TLambda&& filter); // Does not compile };
What can we use instead of lambdas?
The Windows Runtime doesn’t support lambdas, but it supports what you typically use the lambda for, which is providing a callback. The thing that represents a function is a delegate.
You can think of a delegate as the Windows Runtime version of a std::function
. It’s an object that can hold a lambda or a static function or an object combined with a member function.
// C++/WinRT IDL delegate Boolean ThingFilter(Thing thing); runtimeclass MyClass { void ApplyFilter(ThingFilter filter); } // C++/CX public delegate bool ThingFilter(Thing^ thing); public ref class MyClass { public: void ApplyFilter(ThingFilter^ filter); };
You can use the delegate like a function object.
// C++/WinRT void MyClass::ApplyFilter(ThingFilter const& filter) { things.erase(std::remove_if(things.begin(), things.end(), [&](auto&& thing) { return !filter(thing); }), things.end()); } // C++/CX void MyClass::ApplyFilter(ThingFilter^ filter) { things.erase(std::remove_if(things.begin(), things.end(), [&](Thing^ thing) { return !filter(thing); }), things.end()); }
Most language projections let you pass a lambda directly. C++/CX is the outlier here. It requires you to wrap it inside an explicit ThingFilter
. The other languages will do the wrapping automatically.
// C++/WinRT c.ApplyFilter([=](auto&& thing) { return IsOkay(thing); }); // C++/CX c->ApplyFilter( ref new ThingFilter([=](Thing^ thing) { return IsOkay(thing); })); // C# c.ApplyFilter(thing => IsOkay(thing)); // JavaScript c.applyFilter(thing => isOkay(thing)); // Visual Basic c.ApplyFilter(Function (thing As Thing) IsOkay(thing))
Much like in C# we could write event handler as lambda, but we used to create event handlers as delegates.
1) this.Click += (s, arg) =>
{
};
2) this.Click += Form1_Click;
3) this.Click += new EventHandler(Form1_Click);
private void Form1_Click(object sender, EventArgs e)
{
}