{"id":109965,"date":"2024-07-11T07:00:00","date_gmt":"2024-07-11T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109965"},"modified":"2024-06-24T10:37:09","modified_gmt":"2024-06-24T17:37:09","slug":"20240711-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240711-00\/?p=109965","title":{"rendered":"Creating an already-completed asynchronous activity in C++\/WinRT, part 3"},"content":{"rendered":"<p>Last time, we figured out how to <a title=\"Creating an already-completed asynchronous activity in C++\/WinRT, part 2\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240710-00\/?p=109963\"> create an already-completed asynchronous activity in C++\/WinRT<\/a>. Today we&#8217;ll try to generalize it to cover the four kinds of Windows Runtime asynchronous activities.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<th>No progress<\/th>\n<th>Progres<\/th>\n<\/tr>\n<tr>\n<th>No result<\/th>\n<td><code>IAsyncAction<\/code><\/td>\n<td><code>IAsyncActionWithProgress&lt;P&gt;<\/code><\/td>\n<\/tr>\n<tr>\n<th>Result<\/th>\n<td><code>IAsyncOperation<\/code><\/td>\n<td><code>IAsyncOperationWithProgress&lt;T, P&gt;<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>One way to do this is to write four different functions for each category, similar to how we dealt with <i>cv<\/i>-qualifiers before we had <a title=\"C++23's Deducing this: what it is, why it is, how to use it\" href=\"https:\/\/devblogs.microsoft.com\/cppblog\/cpp23-deducing-this\/\"> deducing this<\/a>.<\/p>\n<pre>winrt::Windows::Foundation::IAsyncAction\r\nMakeCompletedAsyncAction()\r\n{\r\n    co_return;\r\n}\r\n\r\ntemplate&lt;typename Progress&gt;\r\nwinrt::Windows::Foundation::IAsyncActionWithProgress&lt;Progress&gt;\r\nMakeCompletedAsyncActionWithProgress()\r\n{\r\n    co_return;\r\n}\r\n\r\ntemplate&lt;typename Result, typename Progress&gt;\r\nwinrt::Windows::Foundation::IAsyncOperation&lt;Result&gt;\r\nMakeCompletedAsyncOperation(Result result)\r\n{\r\n    co_return result;\r\n}\r\n\r\ntemplate&lt;typename Result, typename Progress&gt;\r\nwinrt::Windows::Foundation::IAsyncOperationWithProgress&lt;Result, Progress&gt;\r\nMakeCompletedAsyncOperationWithProgress(Result result)\r\n{\r\n    co_return result;\r\n}\r\n\r\n\/\/ Sample usage:\r\n\r\nwinrt::Windows::Foundation::IAsyncOperation&lt;int&gt;\r\nGetHeightAsync()\r\n{\r\n    return MakeCompletedAsyncOperation(42);\r\n}\r\n\r\nwinrt::Windows::Foundation::\r\n    IAsyncOperationWithProgress&lt;int, HeightProgress&gt;\r\nGetHeightAsync()\r\n{\r\n    return MakeCompletedAsyncOperationWithProgress&lt;\r\n        int, HeightProgress&gt;(42);\r\n}\r\n<\/pre>\n<p>Explicit specialization is required for the <code>WithProgress<\/code> versions, since there is no opportunity to deduce the progress type.<\/p>\n<p>We could combine the four flavors into a single function, though this means that specialization is mandatory.<\/p>\n<pre>template&lt;typename Async, typename... Result&gt;\r\nAsync MakeCompleted(Result... result)\r\n{\r\n    if constexpr (sizeof...(Result) == 0) {\r\n        co_return;\r\n    } else {\r\n        static_assert(sizeof...(Result) == 1);\r\n        co_return std::get&lt;0&gt;(\r\n            std::forward_as_tuple(result...));\r\n    }\r\n}\r\n<\/pre>\n<p>We use a trick in <code>Make\u00adCompleted<\/code> by formally accepting any number of arguments, although we check inside the function body that it is zero or one. In the case where there is one parameter, we use the <code>forward_<wbr \/>as_<wbr \/>tuple<\/code> + <code>get<\/code> technique to <a title=\"Pulling a single item from a C++ parameter pack by its index\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240516-00\/?p=109771\"> pull a single item from a parameter pack<\/a>.<\/p>\n<p>Next time, we&#8217;ll try to write <code>MakeFailed<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Generalizing to the four kinds of Windows Runtime asynchronous activities.<\/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-109965","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Generalizing to the four kinds of Windows Runtime asynchronous activities.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109965","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=109965"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109965\/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=109965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}