{"id":110913,"date":"2025-02-27T07:00:00","date_gmt":"2025-02-27T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110913"},"modified":"2025-02-27T09:48:08","modified_gmt":"2025-02-27T17:48:08","slug":"20250227-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250227-00\/?p=110913","title":{"rendered":"C++\/WinRT implementation inheritance: Notes on <CODE>winrt::implements<\/CODE>, part 7"},"content":{"rendered":"<p>Last time, <a title=\"C++\/WinRT implementation inheritance: Notes on winrt::implements, part 6\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250226-00\/?p=110908\"> we simplified a base class so that it doesn&#8217;t fully implement any interfaces at all<\/a>. So why are we using <code>winrt::implements<\/code> in the first place?<\/p>\n<p>Yeah, why?<\/p>\n<p>Let&#8217;s not.<\/p>\n<pre>\/\/ A simple copy drop target provides no custom feedback\r\n\/\/ and accepts anything by copy.\r\nstruct SimpleCopyDropTarget\r\n{\r\n    winrt::IAsyncOperation&lt;winrt::DataPackageOperation&gt;\r\n        EnterAsync(winrt::CoreDragInfo const&amp; info,\r\n                   winrt::CoreDragUIOverride const&amp;)\r\n    {\r\n        co_return GetOperation(info);\r\n    }\r\n\r\n    winrt::IAsyncOperation&lt;winrt::DataPackageOperation&gt;\r\n        OverAsync(winrt::CoreDragInfo const&amp; info,\r\n                  winrt::CoreDragUIOverride const&amp;)\r\n    {\r\n        co_return GetOperation(info);\r\n    }\r\n\r\n    winrt::IAsyncAction\r\n        LeaveAsync(winrt::CoreDragInfo const&amp;)\r\n    {\r\n        co_return;\r\n    }\r\n\r\n    \/\/ DropAsync must be implemented by derived class\r\n\r\nprotected:\r\n    winrt::DataPackageOperation GetOperation(\r\n        winrt::CoreDragInfo const&amp; info)\r\n    {\r\n        return info.AllowedOperations() &amp;\r\n               winrt::DataPackageOperation::Copy;\r\n    }\r\n};\r\n<\/pre>\n<p>This base class implements some of the methods of <code>ICore\u00adDrop\u00adOperation<\/code>, but it doesn&#8217;t implement <code>DropAsync<\/code>, so it can&#8217;t be used to implement the interface. So we don&#8217;t even pretend to! We don&#8217;t derive from <code>winrt::<wbr \/>implements<\/code> at all. Instead, the derived class just uses this base class to implement some of the interface methods that it declares.<\/p>\n<pre>struct Derived : winrt::implements&lt;\r\n    Derived,\r\n    <span style=\"border: solid 1px currentcolor;\">winrt::ICoreDropOperationTarget<\/span>&gt;,\r\n    <span style=\"border: solid 1px currentcolor;\">SimpleCopyDropTarget<\/span>,\r\n{\r\n    winrt::IAsyncOperation&lt;DataPackageOperation&gt;\r\n        DropAsync(winrt::CoreDragInfo info)\r\n    {\r\n        auto lifetime = get_strong();\r\n\r\n        auto operation = GetOperation(info);\r\n        if (!(operation &amp; winrt::DataPackageOperation::Copy)) {\r\n            co_return winrt::DataPackageOperation::None;\r\n        }\r\n\r\n        \u27e6 process the drop \u27e7\r\n\r\n        co_return winrt::DataPackageOperation::Copy;\r\n    }\r\n};\r\n<\/pre>\n<p>In more general cases, the helper class may need to offer extensibility points to the derived class, and we can use the existing mechanisms (virtual methods, CRTP, deducing this) to ask the derived class for help.<\/p>\n<p>Next time, we&#8217;ll compare the pros and cons of the various options.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Inheritance without involving <CODE>winrt::implements<\/CODE> at all.<\/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-110913","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Inheritance without involving <CODE>winrt::implements<\/CODE> at all.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110913","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=110913"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110913\/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=110913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}