{"id":102920,"date":"2019-09-25T07:00:00","date_gmt":"2019-09-25T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102920"},"modified":"2019-11-07T06:53:22","modified_gmt":"2019-11-07T14:53:22","slug":"20190925-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190925-00\/?p=102920","title":{"rendered":"How do I create a Windows Runtime method that accepts a lambda?"},"content":{"rendered":"<p>A customer wanted to create a Windows Runtime method that accepted a lambda. But lambdas aren&#8217;t valid Windows Runtime types.<\/p>\n<pre>\/\/ C++\/WinRT IDL\r\nruntimeclass MyClass\r\n{\r\n  template&lt;typename TLambda&gt;\r\n  void ApplyFilter(TLambda&amp;&amp; filter); \/\/ Does not compile\r\n}\r\n\r\n\/\/ C++\/CX\r\npublic ref class MyClass\r\n{\r\npublic:\r\n  template&lt;typename TLambda&gt;\r\n  void ApplyFilter(TLambda&amp;&amp; filter); \/\/ Does not compile\r\n};\r\n<\/pre>\n<p>What can we use instead of lambdas?<\/p>\n<p>The Windows Runtime doesn&#8217;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 <i>delegate<\/i>.<\/p>\n<p>You can think of a delegate as the Windows Runtime version of a <code>std::function<\/code>. It&#8217;s an object that can hold a lambda or a static function or an object combined with a member function.<\/p>\n<pre>\/\/ C++\/WinRT IDL\r\ndelegate Boolean ThingFilter(Thing thing);\r\n\r\nruntimeclass MyClass\r\n{\r\n  void ApplyFilter(ThingFilter filter);\r\n}\r\n\r\n\/\/ C++\/CX\r\npublic delegate bool ThingFilter(Thing^ thing);\r\n\r\npublic ref class MyClass\r\n{\r\npublic:\r\n  void ApplyFilter(ThingFilter^ filter);\r\n};\r\n<\/pre>\n<p>You can use the delegate like a function object.<\/p>\n<pre>\/\/ C++\/WinRT\r\nvoid MyClass::ApplyFilter(ThingFilter const&amp; filter)\r\n{\r\n  things.erase(std::remove_if(things.begin(), things.end(),\r\n    [&amp;](auto&amp;&amp; thing) { return !filter(thing); }),\r\n    things.end());\r\n}\r\n\r\n\/\/ C++\/CX\r\nvoid MyClass::ApplyFilter(ThingFilter^ filter)\r\n{\r\n  things.erase(std::remove_if(things.begin(), things.end(),\r\n    [&amp;](Thing^ thing) { return !filter(thing); }),\r\n    things.end());\r\n}\r\n<\/pre>\n<p>Most language projections let you pass a lambda directly. C++\/CX is the outlier here. It requires you to wrap it inside an explicit <code>ThingFilter<\/code>. The other languages will do the wrapping automatically.<\/p>\n<pre>\/\/ C++\/WinRT\r\nc.ApplyFilter([=](auto&amp;&amp; thing) { return IsOkay(thing); });\r\n\r\n\/\/ C++\/CX\r\nc-&gt;ApplyFilter(\r\n    ref new ThingFilter([=](Thing^ thing) { return IsOkay(thing); }));\r\n\r\n\/\/ C#\r\nc.ApplyFilter(thing =&gt; IsOkay(thing));\r\n\r\n\/\/ JavaScript\r\nc.applyFilter(thing =&gt; isOkay(thing));\r\n\r\n\/\/ Visual Basic\r\nc.ApplyFilter(Function (thing As Thing) IsOkay(thing))\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can use a delegate as a generalized lambda.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102920","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can use a delegate as a generalized lambda.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=102920"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102920\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=102920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}