{"id":108474,"date":"2023-07-21T07:00:00","date_gmt":"2023-07-21T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108474"},"modified":"2023-07-21T07:15:57","modified_gmt":"2023-07-21T14:15:57","slug":"20230721-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230721-00\/?p=108474","title":{"rendered":"How to clone a Windows Runtime map in the face of possible concurrent modification, part 3"},"content":{"rendered":"<p>Last time, we <a title=\"How to clone a Windows Runtime map in the face of possible concurrent modification, part 2\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230720-00\/?p=108466\"> developed some functions for cloning a Windows Runtime map via C++\/WinRT<\/a>. This time, we&#8217;ll do it in C++\/CX, for those still using that language.<\/p>\n<pre>template&lt;typename M&gt;\r\nauto clone_as_kvp_vector(M const&amp; m)\r\n{\r\n    using KVP = decltype(m-&gt;First()-&gt;Current);\r\n    std::vector&lt;KVP&gt; pairs;\r\n    unsigned expected;\r\n    unsigned actual;\r\n    do {\r\n        expected = m-&gt;Size;\r\n        pairs.resize(expected + 1);\r\n        try {\r\n            actual = m-&gt;First()-&gt;GetMany(Platform::\r\n                ArrayReference&lt;KVP&gt;(pairs.data(), expected + 1));\r\n        } catch (Platform::ChangedStateException^) {\r\n            continue;\r\n        }\r\n    } while (actual &gt; expected);\r\n    pairs.resize(actual);\r\n    return pairs;\r\n}\r\n\r\n\/\/ override_or_fallback_t unchanged\r\n\r\ntemplate&lt;typename M,\r\n    typename KeyOverride,\r\n    typename ValueOverride&gt;\r\nstruct inferred_runtime_map_traits\r\n{\r\n    using KVP = decltype(std::declval&lt;M&gt;()-&gt;First()-&gt;Current);\r\n\r\n    using Key = override_or_fallback_t&lt;\r\n        KeyOverride,\r\n        decltype(KVP()-&gt;Key)&gt;;\r\n    using Value = override_or_fallback_t&lt;\r\n        ValueOverride,\r\n        decltype(KVP()-&gt;Value)&gt;;\r\n};\r\n\r\n\/\/ inferred_map_traits, inferred_unordered_map_traits,\r\n\/\/ clone_as_map, and clone_as_unordered_map unchanged\r\n\r\ntemplate&lt;typename Key = void,\r\n    typename Value = void,\r\n    typename Compare = void,\r\n    typename M,\r\n    typename Traits = inferred_map_traits\r\n    &lt;M, Key, Value, Compare&gt;&gt;\r\n    auto CloneMap(M const&amp; m,\r\n        typename Traits::Compare const&amp; compare = {})\r\n{\r\n    return ref new Platform::Collections::Map&lt;\r\n        typename Traits::Key,\r\n        typename Traits::Value,\r\n        typename Traits::Compare&gt;(\r\n        clone_as_map&lt;Key, Value, Compare&gt;\r\n        (m, compare));\r\n}\r\n\r\ntemplate&lt;typename Key = void,\r\n    typename Value = void,\r\n    typename Hash = void,\r\n    typename KeyEqual = void,\r\n    typename M,\r\n    typename Traits = inferred_unordered_map_traits\r\n    &lt;M, Key, Value, Hash, KeyEqual&gt;&gt;\r\n    auto CloneUnorderedMap(M const&amp; m,\r\n        typename Traits::Hash const&amp; hash = {},\r\n        typename Traits::KeyEqual const&amp; equal = {})\r\n{\r\n    return ref new Platform::Collections::UnorderedMap&lt;\r\n        typename Traits::Key,\r\n        typename Traits::Hash,\r\n        typename Traits::KeyEqual&gt;(\r\n        clone_as_unordered_map&lt;Key, Value, Hash, KeyEqual&gt;\r\n        (m, hash, equal));\r\n}\r\n<\/pre>\n<p>Hm, I thought this was going to introduce new wrinkles into the story, but I was pleasantly surprised: Everything translated to C++\/CX in a straightforward manner with no gotchas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Doing it one more time, for C++\/CX.<\/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-108474","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Doing it one more time, for C++\/CX.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108474","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=108474"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108474\/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=108474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}