{"id":102456,"date":"2019-04-29T07:00:00","date_gmt":"2019-04-29T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102456"},"modified":"2022-10-05T07:35:21","modified_gmt":"2022-10-05T14:35:21","slug":"20190429-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190429-00\/?p=102456","title":{"rendered":"Spotting problems with destructors for C++ temporaries"},"content":{"rendered":"<p>Consider the <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20180831-00\/?p=99625\"><code>unique_<\/code><code>handle<\/code><\/a>. It specializes <code>std::<\/code><code>unique_<\/code><code>ptr<\/code> to support Windows kernel handles. It lets you get all the niceties of <code>std::<\/code><code>unique_<\/code><code>ptr<\/code> with just a handful of lines of code.<\/p>\n<p>But then you have the problem of interoperating with the rest of the system. For example, how would you use a <code>unique_<\/code><code>handle<\/code> to receive the result of a duplication?<\/p>\n<pre>unique_handle originalHandle = ...;\r\nunique_handle duplicateHandle;\r\n\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), &amp;duplicateHandle,\r\n      0, FALSE, DUPLICATE_SAME_ACCESS)) { ... }\r\n<\/pre>\n<p>This doesn&#8217;t compile because the <code>operator&amp;<\/code> for a <code>unique_<\/code><code>ptr<\/code> doesn&#8217;t give you a pointer to the inner raw pointer. You&#8217;ll have to perform the operation in two steps.<\/p>\n<pre>HANDLE rawDuplicateHandle = nullptr;\r\n\r\n\/\/ First, get a raw handle as the duplicate.\r\nauto result = DuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), &amp;rawDuplicateHandle,\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n\r\n\/\/ Then set it into the smart pointer.\r\nduplicateHandle.reset(rawDuplicateHandle);\r\n\r\n\/\/ Then see if it worked.\r\nif (result) { ... }\r\n<\/pre>\n<p>We could tune this a little:<\/p>\n<pre>HANDLE rawDuplicateHandle;\r\n\r\n\/\/ Out with the old.\r\nduplicateHandle.reset();\r\n\r\n\/\/ Try to get a new handle.\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), &amp;rawDuplicateHandle,\r\n      0, FALSE, DUPLICATE_SAME_ACCESS)) {\r\n\r\n  \/\/ Save the new handle back into the smart pointer.\r\n  duplicateHandle.reset(rawDuplicateHandle);\r\n\r\n  ...\r\n}\r\n<\/pre>\n<p>But the underlying issue remains: Bridging the gap between the C++ <code>unique_<\/code><code>ptr<\/code> and the system function that wants you to pass the address of a <code>HANDLE<\/code>.<\/p>\n<p>You might decide to create a helper class whose job is to encapsulate this two-step dance, acting as a proxy between the raw handle and the smart pointer.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(output) { }\r\n\r\n  ~handle_proxy() { m_output.reset(m_rawHandle); }\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n\r\n  \/\/ Not copyable, not movable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  unique_handle&amp; m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n<\/pre>\n<p>This proxy object lets you pass a <code>HANDLE*<\/code> to functions that return a handle through a pointer, and when the proxy is destructed, it transfers the raw handle into the smart pointer.<\/p>\n<pre>DuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), handle_proxy(duplicateHandle).addressof(),\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n<\/pre>\n<p>What&#8217;s happening here is that we create a temporary <code>handle_<\/code><code>proxy<\/code> object to pass to the <code>Duplicate\u00adHandle<\/code> function. This temporary object remembers the <code>unique_<\/code><code>handle<\/code> that it is proxying for, and produces the address of a plain old <code>HANDLE<\/code> which is what gets passed to the to the <code>Duplicate\u00adHandle<\/code> function. After the <code>Duplicate\u00adHandle<\/code> function returns, the temporary is destructed, and the destructor takes the raw handle in <code>m_rawHandle<\/code> and puts it into the smart pointer.<\/p>\n<p>As a convenience, you could add a conversion operator to save people the hassle of having to say <code>addressof<\/code> all over the place.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(output) { }\r\n\r\n  ~handle_proxy() { m_output.reset(m_rawHandle); }\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n  <span style=\"color: blue;\">operator HANDLE*() { return addressof(); }<\/span>\r\n\r\n  \/\/ Not copyable, not movable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  unique_handle&amp; m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n\r\nDuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), <span style=\"color: blue;\">handle_proxy(duplicateHandle)<\/span>,\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n<\/pre>\n<p>Everything&#8217;s looking great, until somebody does this:<\/p>\n<pre>\/\/ Try to duplicate the handle for EVENT_MODIFY_STATE access\r\n\/\/ and reset it.\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0) &amp;&amp;\r\n    ResetEvent(duplicateHandle.get()) { ... }\r\n<\/pre>\n<p>Do you see the problem?<\/p>\n<p>The C++ rules for temporary objects is that they are destructed at the end of the &#8220;full expression&#8221; that contains them. This means that the temporary <code>handle_<\/code><code>proxy<\/code> object doesn&#8217;t get destructed until the entire expression inside the <code>if<\/code> statement has been evaluated, which means that the <code>Reset\u00adEvent<\/code> happens before the proxy&#8217;s destructor can transfer the raw pointer into the smart pointer.<\/p>\n<ol>\n<li>Create temporary <code>handle_<\/code><code>proxy<\/code>.<\/li>\n<li>Convert it to a <code>HANDLE*<\/code>.<\/li>\n<li>Call <code>Duplicate\u00adHandle<\/code>.<\/li>\n<li>Assuming <code>Duplicate\u00adHandle<\/code> succeeds, call <code>Reset\u00adEvent<\/code> with the <code>duplicate\u00adHandle<\/code>.<\/li>\n<li>Destruct the <code>handle_<\/code><code>proxy<\/code>, which copies the raw handle into <code>duplicate\u00adHandle<\/code>.<\/li>\n<\/ol>\n<p>We want step 5 to happen before step 4, but the C++ rules for destruction of temporary objects forces the proxy to linger until after the expression has been evaluated.<\/p>\n<p>What can we do?<\/p>\n<p>One option is to introduce a dreaded macro which forces temporaries to be destructed prematurely.<\/p>\n<pre>#define DESTRUCT_TEMPORARIES(v) [&amp;]() { return (v); }()\r\n<\/pre>\n<p>This macro wraps the argument inside an immediately-evaluated lambda and propagates the value of the expression. This doesn&#8217;t seem to accomplish anything, but what it does is pull <code>v<\/code> into its own full expression, thereby forcing its temporaries to be destructed immediately after its evaluation.<\/p>\n<pre>if (<span style=\"color: blue;\">DESTRUCT_TEMPORARIES(<\/span>DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0)<span style=\"color: blue;\">)<\/span> &amp;&amp;\r\n    ResetEvent(duplicateHandle.get()) { ... }\r\n<\/pre>\n<p>This is ugly for multiple reasons. One is that <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20190115-00\/?p=100705\">it encourages passing multi-line entities to macros<\/a>. Second, it&#8217;s a macro used <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#es30-dont-use-macros-for-program-text-manipulation\">for something other than <code>#ifdef<\/code><\/a>.<\/p>\n<p>Another option is to manage the transfer explicitly.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(std::addressof(output)) { }\r\n\r\n  ~handle_proxy() { transfer(); }\r\n\r\n  <span style=\"color: blue;\">void transfer()\r\n  {\r\n    if (m_output) {\r\n      std::exchange(m_output, {})-&gt;reset(m_rawHandle);\r\n    }\r\n  }<\/span>\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n  operator HANDLE*() { return addressof(); }\r\n\r\n  \/\/ Not copyable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  \/\/ Movable.\r\n  handle_proxy(handle_proxy&amp;&amp; other)\r\n  : m_output(std::exchange(other.m_output, {})),\r\n    m_rawHandle(std::exchange(other.m_rawHandle, {})) { }\r\n\r\n  handle_proxy&amp; operator=(handle_proxy&amp;&amp; other)\r\n  {\r\n    transfer();\r\n    m_output = std::exchange(other.m_output, {});\r\n    m_rawHandle = std::exchange(other.m_rawHandle, {});\r\n  }\r\n\r\n  unique_handle* m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n<\/pre>\n<p>In this version, we capture a raw pointer to the <code>unique_<\/code><code>handle<\/code> so that we have a way to keep track of whether the result has been transferred or not: If the pointer is <code>nullptr<\/code>, then the transfer has already taken place.<\/p>\n<p>Now that we have a way to say &#8220;Nothing to transfer,&#8221; we can add a move constructor and move assignment operator, both of which leave the source in the &#8220;Nothing to do&#8221; state.<\/p>\n<p>You can continue to use this version of the <code>handle_proxy<\/code> the same as the previous version, or you can opt to trigger the transfer early:<\/p>\n<pre>if (<span style=\"color: blue;\">auto proxy = handle_proxy(duplicateHandle);<\/span>\r\n    DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), proxy,\r\n      EVENT_MODIFY_STATE, FALSE, 0)<span style=\"color: blue;\">)<\/span> &amp;&amp;\r\n    (<span style=\"color: blue;\">proxy.transfer()<\/span>, ResetEvent(duplicateHandle.get())) { ... }\r\n<\/pre>\n<p>This is still pretty ugly. You can clean it up a little by having the transfer function also return the handle that it transferred.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  ...\r\n  <span style=\"color: blue;\">HANDLE<\/span> transfer()\r\n  {\r\n    if (m_output) {\r\n      std::exchange(m_output, {})-&gt;reset(m_rawHandle);\r\n    }\r\n    <span style=\"color: blue;\">return m_rawHandle;<\/span>\r\n  }\r\n  ...\r\n};\r\n\r\nif (auto proxy = handle_proxy(duplicateHandle);\r\n    DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), proxy,\r\n      EVENT_MODIFY_STATE, FALSE, 0)) &amp;&amp;\r\n    ResetEvent(<span style=\"color: blue;\">proxy.transfer()<\/span>)) { ... }\r\n<\/pre>\n<p>It&#8217;s a little less ugly, but also more puzzling.<\/p>\n<p>Perhaps the way out is simply to split it into two expressions.<\/p>\n<pre>if (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0)) {\r\n\r\n  \/\/ Test separately to give handly_proxy's destructor a chance to\r\n  \/\/ put the result into duplicateHandle before we read it out.\r\n  if (ResetEvent(duplicateHandle.get())) { ... }\r\n}\r\n<\/pre>\n<p>If you are willing to wrap every system function you need to interact with, you could add a wrapper that returns a <code>unique_<\/code><code>handle<\/code> directly.<\/p>\n<pre>unique_handle DuplicateAndReturnHandle(\r\n    HANDLE sourceProcess,\r\n    HANDLE sourceHandle,\r\n    HANDLE targetProcess,\r\n    DWORD desiredAccess,\r\n    BOOL  inheritHandle,\r\n    DWORD options)\r\n{\r\n  HANDLE targetHandle;\r\n  if (DuplicateHandle(sourceProcess, sourceHandle,\r\n                      targetProcess, &amp;targetHandle,\r\n                      desiredAccess, inheritHandle, options)) {\r\n    return unique_handle{ targetHandle };\r\n  }\r\n  return {};\r\n}\r\n\r\nif ((duplicateHandle = DuplicateAndReturnHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), EVENT_MODIFY_STATE, FALSE, 0)) &amp;&amp;\r\n  ResetEvent(duplicateHandle.get())) { ... }\r\n}\r\n<\/pre>\n<p>The downside of this is that you have an entire library of wrapper functions you&#8217;ll have to maintain. And if the function is like <code>Reg\u00adOpen\u00adKey\u00adEx<\/code> and returns information in addition to the handle, you&#8217;ll have to put it into a <code>std::<\/code><code>tuple<\/code> or a <code>std::<\/code><code>variant<\/code>, which is another level of bother.<\/p>\n<p>Consider the <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20180831-00\/?p=99625\"> <code>unique_<\/code><code>handle<\/code><\/a>. It specializes <code>std::<\/code><code>unique_<\/code><code>ptr<\/code> to support Windows kernel handles. It lets you get all the niceties of <code>std::<\/code><code>unique_<\/code><code>ptr<\/code> with just a handful of lines of code.<\/p>\n<p>But then you have the problem of interoperating with the rest of the system. For example, how would you use a <code>unique_<\/code><code>handle<\/code> to receive the result of a duplication?<\/p>\n<pre>unique_handle originalHandle = ...;\r\nunique_handle duplicateHandle;\r\n\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), &amp;duplicateHandle,\r\n      0, FALSE, DUPLICATE_SAME_ACCESS)) { ... }\r\n<\/pre>\n<p>This doesn&#8217;t compile because the <code>operator&amp;<\/code> for a <code>unique_<\/code><code>ptr<\/code> doesn&#8217;t give you a pointer to the inner raw pointer. You&#8217;ll have to perform the operation in two steps.<\/p>\n<pre>HANDLE rawDuplicateHandle = nullptr;\r\n\r\n\/\/ First, get a raw handle as the duplicate.\r\nauto result = DuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), &amp;rawDuplicateHandle,\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n\r\n\/\/ Then set it into the smart pointer.\r\nduplicateHandle.reset(rawDuplicateHandle);\r\n\r\n\/\/ Then see if it worked.\r\nif (result) { ... }\r\n<\/pre>\n<p>We could tune this a little:<\/p>\n<pre>HANDLE rawDuplicateHandle;\r\n\r\n\/\/ Out with the old.\r\nduplicateHandle.reset();\r\n\r\n\/\/ Try to get a new handle.\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), &amp;rawDuplicateHandle,\r\n      0, FALSE, DUPLICATE_SAME_ACCESS)) {\r\n\r\n  \/\/ Save the new handle back into the smart pointer.\r\n  duplicateHandle.reset(rawDuplicateHandle);\r\n\r\n  ...\r\n}\r\n<\/pre>\n<p>But the underlying issue remains: Bridging the gap between the C++ <code>unique_<\/code><code>ptr<\/code> and the system function that wants you to pass the address of a <code>HANDLE<\/code>.<\/p>\n<p>You might decide to create a helper class whose job is to encapsulate this two-step dance, acting as a proxy between the raw handle and the smart pointer.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(output) { }\r\n\r\n  ~handle_proxy() { m_output.reset(m_rawHandle); }\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n\r\n  \/\/ Not copyable, not movable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  unique_handle&amp; m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n<\/pre>\n<p>This proxy object lets you pass a <code>HANDLE*<\/code> to functions that return a handle through a pointer, and when the proxy is destructed, it transfers the raw handle into the smart pointer.<\/p>\n<pre>DuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), handle_proxy(duplicateHandle).addressof(),\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n<\/pre>\n<p>What&#8217;s happening here is that we create a temporary <code>handle_<\/code><code>proxy<\/code> object to pass to the <code>Duplicate\u00adHandle<\/code> function. This temporary object remembers the <code>unique_<\/code><code>handle<\/code> that it is proxying for, and produces the address of a plain old <code>HANDLE<\/code> which is what gets passed to the to the <code>Duplicate\u00adHandle<\/code> function. After the <code>Duplicate\u00adHandle<\/code> function returns, the temporary is destructed, and the destructor takes the raw handle in <code>m_rawHandle<\/code> and puts it into the smart pointer.<\/p>\n<p>As a convenience, you could add a conversion operator to save people the hassle of having to say <code>addressof<\/code> all over the place.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(output) { }\r\n\r\n  ~handle_proxy() { m_output.reset(m_rawHandle); }\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n  <span style=\"color: #08f;\">operator HANDLE*() { return addressof(); }<\/span>\r\n\r\n  \/\/ Not copyable, not movable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  unique_handle&amp; m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n\r\nDuplicateHandle(\r\n    GetCurrentProcess(), originalHandle.get(),\r\n    GetCurrentProcess(), <span style=\"color: #08f;\">handle_proxy(duplicateHandle)<\/span>,\r\n    0, FALSE, DUPLICATE_SAME_ACCESS);\r\n<\/pre>\n<p>Everything&#8217;s looking great, until somebody does this:<\/p>\n<pre>\/\/ Try to duplicate the handle for EVENT_MODIFY_STATE access\r\n\/\/ and reset it.\r\nif (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0) &amp;&amp;\r\n    ResetEvent(duplicateHandle.get()) { ... }\r\n<\/pre>\n<p>Do you see the problem?<\/p>\n<p>The C++ rules for temporary objects is that they are destructed at the end of the &#8220;full expression&#8221; that contains them. This means that the temporary <code>handle_<\/code><code>proxy<\/code> object doesn&#8217;t get destructed until the entire expression inside the <code>if<\/code> statement has been evaluated, which means that the <code>Reset\u00adEvent<\/code> happens before the proxy&#8217;s destructor can transfer the raw pointer into the smart pointer.<\/p>\n<ol>\n<li>Create temporary <code>handle_<\/code><code>proxy<\/code>.<\/li>\n<li>Convert it to a <code>HANDLE*<\/code>.<\/li>\n<li>Call <code>Duplicate\u00adHandle<\/code>.<\/li>\n<li>Assuming <code>Duplicate\u00adHandle<\/code> succeeds, call <code>Reset\u00adEvent<\/code> with the <code>duplicate\u00adHandle<\/code>.<\/li>\n<li>Destruct the <code>handle_<\/code><code>proxy<\/code>, which copies the raw handle into <code>duplicate\u00adHandle<\/code>.<\/li>\n<\/ol>\n<p>We want step 5 to happen before step 4, but the C++ rules for destruction of temporary objects forces the proxy to linger until after the expression has been evaluated.<\/p>\n<p>What can we do?<\/p>\n<p>One option is to introduce a dreaded macro which forces temporaries to be destructed prematurely.<\/p>\n<pre>#define DESTRUCT_TEMPORARIES(v) [&amp;]() { return (v); }()\r\n<\/pre>\n<p>This macro wraps the argument inside an immediately-evaluated lambda and propagates the value of the expression. This doesn&#8217;t seem to accomplish anything, but what it does is pull <code>v<\/code> into its own full expression, thereby forcing its temporaries to be destructed immediately after its evaluation.<\/p>\n<pre>if (<span style=\"color: #08f;\">DESTRUCT_TEMPORARIES(<\/span>DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0)<span style=\"color: #08f;\">)<\/span> &amp;&amp;\r\n    ResetEvent(duplicateHandle.get()) { ... }\r\n<\/pre>\n<p>This is ugly for multiple reasons. One is that <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20190115-00\/?p=100705\"> it encourages passing multi-line entities to macros<\/a>. Second, it&#8217;s a macro used <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#es30-dont-use-macros-for-program-text-manipulation\"> for something other than <code>#ifdef<\/code><\/a>.<\/p>\n<p>Another option is to manage the transfer explicitly.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  handle_proxy(unique_handle&amp; output)\r\n  : m_output(std::addressof(output)) { }\r\n\r\n  ~handle_proxy() { transfer(); }\r\n\r\n  <span style=\"color: #08f;\">void transfer()\r\n  {\r\n    if (m_output) {\r\n      std::exchange(m_output, {})-&gt;reset(m_rawHandle);\r\n    }\r\n  }<\/span>\r\n\r\n  HANDLE* addressof() { return &amp;m_rawHandle; }\r\n  operator HANDLE*() { return addressof(); }\r\n\r\n  \/\/ Not copyable.\r\n  handle_proxy(const handle_proxy&amp;) = delete;\r\n  handle_proxy&amp; operator=(const handle_proxy&amp;) = delete;\r\n\r\n  \/\/ Movable.\r\n  handle_proxy(handle_proxy&amp;&amp; other)\r\n  : m_output(std::exchange(other.m_output, {})),\r\n    m_rawHandle(std::exchange(other.m_rawHandle, {})) { }\r\n\r\n  handle_proxy&amp; operator=(handle_proxy&amp;&amp; other)\r\n  {\r\n    transfer();\r\n    m_output = std::exchange(other.m_output, {});\r\n    m_rawHandle = std::exchange(other.m_rawHandle, {});\r\n  }\r\n\r\n  unique_handle* m_output;\r\n  HANDLE m_rawHandle = nullptr;\r\n};\r\n<\/pre>\n<p>In this version, we capture a raw pointer to the <code>unique_<\/code><code>handle<\/code> so that we have a way to keep track of whether the result has been transferred or not: If the pointer is <code>nullptr<\/code>, then the transfer has already taken place.<\/p>\n<p>Now that we have a way to say &#8220;Nothing to transfer,&#8221; we can add a move constructor and move assignment operator, both of which leave the source in the &#8220;Nothing to do&#8221; state.<\/p>\n<p>You can continue to use this version of the <code>handle_proxy<\/code> the same as the previous version, or you can opt to trigger the transfer early:<\/p>\n<pre>if (<span style=\"color: #08f;\">auto proxy = handle_proxy(duplicateHandle);<\/span>\r\n    DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), proxy,\r\n      EVENT_MODIFY_STATE, FALSE, 0)<span style=\"color: #08f;\">)<\/span> &amp;&amp;\r\n    (<span style=\"color: #08f;\">proxy.transfer()<\/span>, ResetEvent(duplicateHandle.get())) { ... }\r\n<\/pre>\n<p>This is still pretty ugly. You can clean it up a little by having the transfer function also return the handle that it transferred.<\/p>\n<pre>struct handle_proxy\r\n{\r\n  ...\r\n  <span style=\"color: #08f;\">HANDLE<\/span> transfer()\r\n  {\r\n    if (m_output) {\r\n      std::exchange(m_output, {})-&gt;reset(m_rawHandle);\r\n    }\r\n    <span style=\"color: #08f;\">return m_rawHandle;<\/span>\r\n  }\r\n  ...\r\n};\r\n\r\nif (auto proxy = handle_proxy(duplicateHandle);\r\n    DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), proxy,\r\n      EVENT_MODIFY_STATE, FALSE, 0)) &amp;&amp;\r\n    ResetEvent(<span style=\"color: #08f;\">proxy.transfer()<\/span>)) { ... }\r\n<\/pre>\n<p>It&#8217;s a little less ugly, but also more puzzling.<\/p>\n<p>Perhaps the way out is simply to split it into two expressions.<\/p>\n<pre>if (DuplicateHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), handle_proxy(duplicateHandle),\r\n      EVENT_MODIFY_STATE, FALSE, 0)) {\r\n\r\n  \/\/ Test separately to give handly_proxy's destructor a chance to\r\n  \/\/ put the result into duplicateHandle before we read it out.\r\n  if (ResetEvent(duplicateHandle.get())) { ... }\r\n}\r\n<\/pre>\n<p>If you are willing to wrap every system function you need to interact with, you could add a wrapper that returns a <code>unique_<\/code><code>handle<\/code> directly.<\/p>\n<pre>unique_handle DuplicateAndReturnHandle(\r\n    HANDLE sourceProcess,\r\n    HANDLE sourceHandle,\r\n    HANDLE targetProcess,\r\n    DWORD desiredAccess,\r\n    BOOL  inheritHandle,\r\n    DWORD options)\r\n{\r\n  HANDLE targetHandle;\r\n  if (DuplicateHandle(sourceProcess, sourceHandle,\r\n                      targetProcess, &amp;targetHandle,\r\n                      desiredAccess, inheritHandle, options)) {\r\n    return unique_handle{ targetHandle };\r\n  }\r\n  return {};\r\n}\r\n\r\nif ((duplicateHandle = DuplicateAndReturnHandle(\r\n      GetCurrentProcess(), originalHandle.get(),\r\n      GetCurrentProcess(), EVENT_MODIFY_STATE, FALSE, 0)) &amp;&amp;\r\n  ResetEvent(duplicateHandle.get())) { ... }\r\n}\r\n<\/pre>\n<p>The downside of this is that you have an entire library of wrapper functions you&#8217;ll have to maintain. And if the function is like <code>Reg\u00adOpen\u00adKey\u00adEx<\/code> and returns information in addition to the handle, you&#8217;ll have to put it into a <code>std::<\/code><code>tuple<\/code> or a <code>std::<\/code><code>variant<\/code>, which is another level of bother.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s sometimes later than you want.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102456","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s sometimes later than you want.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102456","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=102456"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102456\/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=102456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}