{"id":107885,"date":"2023-03-01T07:00:00","date_gmt":"2023-03-01T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107885"},"modified":"2023-03-01T07:16:01","modified_gmt":"2023-03-01T15:16:01","slug":"20230301-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230301-00\/?p=107885","title":{"rendered":"If you want to sort a Windows Runtime collection, you may first want to capture it into something a bit easier to manipulate"},"content":{"rendered":"<p>A customer wanted to sort a Windows Runtime collection. The obvious thing to try is<\/p>\n<pre>template&lt;typename T, typename Compare&gt;\r\nvoid SortObservableVector(\r\n    winrt::IObservableVector&lt;T&gt; const&amp; observable,\r\n    Compare comp)\r\n{\r\n    std::sort(begin(observable), end(observable),\r\n        [&amp;](auto&amp;&amp; a, auto&amp;&amp; b)\r\n        { return comp(a, b); });\r\n}\r\n<\/pre>\n<p>This works, but you can do better.<\/p>\n<p>One problem with this version is that we are operating on an observable vector, which means that every vector operation raises a <code>Vector\u00adChanged<\/code> event, and the observers of this vector will get spammed with events as the sort operation proceeds.<\/p>\n<p>Another problem is that every operation on the observable vector is a virtual method call. Depending on what you&#8217;re sorting, this virtual method call overhead could be insignificant, or it could overwhelm the actual work you&#8217;re trying to do.<\/p>\n<p>One way to avoid both of the problem is to <a title=\"How do I make a clone of a Windows Runtime vector in C++\/WinRT?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20191122-00\/?p=103123\"> slurp the contents of the observable vector into a <code>std::vector<\/code><\/a>, sort the <code>std::vector<\/code>, and then <a title=\"How do I set multiple items to a Windows Runtime vector in a single call?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200727-00\/?p=104008\"> shove the results back in<\/a>.<\/p>\n<pre>template&lt;typename T, typename Compare&gt;\r\nvoid SortObservableVector(\r\n    winrt::IObservableVector&lt;T&gt; const&amp; observable,\r\n    Compare&amp;&amp; comp)\r\n{\r\n    \/\/ Slurp into a vector\r\n    std::vector&lt;T&gt; v(observable.Size(),\r\n        <a title=\"Producing an empty Windows Runtime type in C++\/WinRT\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220504-00\/?p=106569\">winrt_empty_value<\/a>&lt;T&gt;());\r\n    observable.GetMany(0, v);\r\n\r\n    \/\/ Sort the vector\r\n    std::sort(begin(v), end(v),\r\n        std::forward&lt;Compare&gt;(comp));\r\n\r\n    \/\/ Shove the results back in\r\n    observable.ReplaceAll(v);\r\n}\r\n<\/pre>\n<p><b>Bonus chatter<\/b>: The <a href=\"https:\/\/github.com\/microsoft\/wil\"> Windows Implementation Library<\/a> has a helper function <code>wil::to_vector<\/code> which wraps up the &#8220;slurp into a vector&#8221; while also addressing the race conditions I warned about in that earlier article.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Moving everything into the same universe.<\/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-107885","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Moving everything into the same universe.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107885","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=107885"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107885\/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=107885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}