{"id":104427,"date":"2020-11-06T07:00:00","date_gmt":"2020-11-06T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104427"},"modified":"2020-11-06T07:03:48","modified_gmt":"2020-11-06T15:03:48","slug":"20201106-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20201106-00\/?p=104427","title":{"rendered":"How do I save a C++\/WinRT array_view as a com_array?"},"content":{"rendered":"<p>If you have a Windows Runtime class with a property whose Windows Runtime type is an array, then the C++\/WinRT projection expresses the property setter and getter as follows:<\/p>\n<pre>\/\/ Set array\r\nvoid IntArray(winrt::array_view&lt;int32_t const&gt; const&amp; value);\r\n\r\n\/\/ Get array\r\nwinrt::com_array&lt;int32_t&gt; IntArray();\r\n<\/pre>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200205-00\/?p=103398\"> We saw earlier<\/a> that these correspond to the <code>PassArray<\/code> and <code>ReceiveArray<\/code> patterns, respectively.<\/p>\n<p>How would you implement the backing store for this property?<\/p>\n<p>Well, the first thing to note is that the backing store should <i>not<\/i> be an <code>array_view<\/code>, because an <code>array_view<\/code> is a non-owning view into somebody else&#8217;s data. If your setter saved just the <code>array_view<\/code>, then it would be left with a dangling pointer, because the <code>array_view<\/code> parameter is valid only for the duration of the call.<\/p>\n<p>You realize that what you want to do is save a copy of the contents of an <code>array_view<\/code>. One option is to save it in a <code>com_array<\/code>, but there is no obvious way to create a <code>com_array<\/code> that is a copy of the contents of an <code>array_view<\/code>, seeing as there&#8217;s no constructor that takes an <code>array_view<\/code>.<\/p>\n<p>You need to use the two-iterator constructor for <code>com_array<\/code>. This creates a copy of the provided range of data and saves it in a <code>com_array<\/code>.<\/p>\n<p>Similarly, to return the <code>com_array<\/code>, you need to construct the return value in the same way. The <code>com_array<\/code> is not copyable, so you&#8217;ll have to use the two-iterator constructor.<\/p>\n<pre>struct Class : ClassT&lt;Class&gt;\r\n{\r\nprivate:\r\n  winrt::com_array&lt;int32_t&gt; int_array_;\r\n\r\npublic:\r\n  void IntArray(winrt::array_view&lt;int32_t const&gt; const&amp; value)\r\n  {\r\n    <span style=\"color: blue;\">int_array_ = { value.begin(), value.end() };<\/span>\r\n  }\r\n\r\n  auto IntArray()\r\n  {\r\n    <span style=\"color: blue;\">return winrt::com_array\r\n      { int_array_.begin(), int_array_.end() };<\/span>\r\n  }\r\n};\r\n<\/pre>\n<p>We take advantage of <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/class_template_argument_deduction\"> class template argument deduction (CTAD)<\/a> to avoid having to repeat the type <code>int32_t<\/code> when constructing the <code>com_array<\/code>. The full version would have been<\/p>\n<pre>    return winrt::com_array&lt;int32_t&gt;\r\n      { int_array_.begin(), int_array_.end() };\r\n<\/pre>\n<p>The <code>com_array<\/code> is not copyable, but it <i>is<\/i> movable, so if you want to just give it away, you can <code>std::move<\/code> it. You don&#8217;t want to do that for a property backing store, but maybe it&#8217;ll come in handy in other cases.<\/p>\n<p>If you intend to do something with the backing store beyond simply using it to hold data, you might want to use a more versatile data structure like a <code>std::vector<\/code>. Fortunately, a <code>com_array<\/code> can construct from a vector, so you can do this:<\/p>\n<pre>struct Class : ClassT&lt;Class&gt;\r\n{\r\nprivate:\r\n  <span style=\"color: blue;\">std::vector&lt;int32_t&gt; int_vector_;<\/span>\r\n\r\npublic:\r\n  void IntArray(winrt::array_view&lt;int32_t const&gt; const&amp; value)\r\n  {\r\n    <span style=\"color: blue;\">int_vector_ = { value.begin(), value.end() };<\/span>\r\n  }\r\n\r\n  auto IntArray()\r\n  {\r\n    <span style=\"color: blue;\">return winrt::com_array{ int_vector_ };<\/span>\r\n  }\r\n};\r\n<\/pre>\n<p>Here, we take advantage of a deduction guide (introduced in <a href=\"https:\/\/github.com\/microsoft\/cppwinrt\/releases\/tag\/2.0.200601.2\"> version 2.0.200601.2<\/a>) to avoid having to specialize the <code>winrt::com_array<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There&#8217;s a not-entirely-obvious constructor for that.<\/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-104427","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>There&#8217;s a not-entirely-obvious constructor for that.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104427","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=104427"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104427\/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=104427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}