{"id":110889,"date":"2025-02-19T07:00:00","date_gmt":"2025-02-19T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110889"},"modified":"2025-02-19T10:52:32","modified_gmt":"2025-02-19T18:52:32","slug":"20250219-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250219-00\/?p=110889","title":{"rendered":"C++\/WinRT implementation inheritance: Notes on <CODE>winrt::implements<\/CODE>, part 1"},"content":{"rendered":"<p>The C++\/WinRT library provides the <code>winrt::implements<\/code> template type for implementing Windows Runtime objects. The general pattern for it is<\/p>\n<pre>struct <span style=\"border: solid 1px currentcolor;\">MyThing<\/span> : winrt::implements&lt;<span style=\"border: solid 1px currentcolor;\">MyThing<\/span>, \u27e6 other stuff \u27e7&gt;\r\n{\r\n    \u27e6 implementation details \u27e7\r\n};\r\n<\/pre>\n<p>You repeat the name of the derived type as the first template parameter because <code>implements<\/code> uses the curiously recurring template pattern (CRTP) to access methods of its derived type.<\/p>\n<p>The &#8220;other stuff&#8221; can contain the following:<\/p>\n<ul>\n<li>A C++\/WinRT interface such as <code>winrt::Windows::Foundation::IMemoryBuffer<\/code>.<\/li>\n<li>A classic COM interface such as <code>IStream<\/code>. (Requires that you enable classic COM support.)<\/li>\n<li>A C++\/WinRT runtime class as <code>winrt::Windows::Foundation::Uri<\/code>. (Not recommended.)<\/li>\n<li>A marker class such as <code>non_agile<\/code>.<\/li>\n<li>Another <code>winrt::implements<\/code>. (Maximum 1.)<\/li>\n<\/ul>\n<p>Let&#8217;s get the middle item out of the way: Specifying a C++\/WinRT runtime class is equivalent to specifying its default interface. This is actually more of a curse than a blessing, for in the case that the C++\/WinRT runtime class has multiple interfaces, only the first one is used, and the rest are ignored! This means that when you write<\/p>\n<pre>struct MockMemoryBuffer : winrt::implements&lt;MockMemoryBuffer,\r\n    winrt::Windows::Foundation::MemoryBuffer&gt;\r\n{\r\n    \u27e6 implementation details \u27e7\r\n};\r\n<\/pre>\n<p>you are implementing only the <code>IMemoryBuffer<\/code> interface and none of the other interfaces like <code>IClosable<\/code>. It <i>looks like<\/i> you&#8217;re implementing all of <code>MemoryBuffer<\/code>, but you&#8217;re not.<\/p>\n<p>So don&#8217;t write that. It&#8217;s misleading. Just write<\/p>\n<pre>struct MockMemoryBuffer : winrt::implements&lt;MockMemoryBuffer,\r\n    winrt::Windows::Foundation::<span style=\"border: solid 1px currentcolor;\">IMemoryBuffer<\/span>&gt;\r\n{\r\n    \u27e6 implementation details \u27e7\r\n};\r\n<\/pre>\n<p>and then it&#8217;s clear that you implemented only one of the required interfaces, and then you&#8217;ll remember to implement the other one.<\/p>\n<pre>struct MockMemoryBuffer : winrt::implements&lt;MockMemoryBuffer,\r\n    winrt::Windows::Foundation::IMemoryBuffer,\r\n    <span style=\"border: solid 1px currentcolor;\">winrt::Windows::Foundation::IClosable<\/span>&gt;\r\n{\r\n    \u27e6 implementation details \u27e7\r\n};\r\n<\/pre>\n<p>Fortunately, implementing somebody else&#8217;s runtime class typically happens only when writing mocks, so the problem tends to arise in testing rather than in production.<\/p>\n<p>If you are implementing a runtime class declared in an IDL file, then don&#8217;t use <code>winrt::<wbr \/>implements<\/code> directly. Instead, use the autogenerated T-template, which fills in all of the required interfaces for you.<\/p>\n<pre>\/\/ automatically implements everything declared in the IDL\r\n\/\/ need to declare only \"bonus\" interfaces not listed in the IDL\r\nstruct Widget : <span style=\"border: solid 1px currentcolor;\">WidgetT<\/span>&lt;Widget, \u27e6 other stuff \u27e7&gt;\r\n{\r\n    \u27e6 implementation details \u27e7\r\n};\r\n<\/pre>\n<p>Next time, we&#8217;ll look at how <code>winrt::<wbr \/>implements<\/code> combines with C++ class inheritance.<\/p>\n<p><b>Bonus chatter<\/b>: How do I know this? I read <a href=\"https:\/\/github.com\/microsoft\/cppwinrt\/blob\/4bc0f82975e794cfc73306c0a023a77132324351\/strings\/base_implements.h\"> the C++\/WinRT code<\/a> and figured it out. You too can become an expert in something by just reading the code and figuring it out.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A closer look at the parameters to the <CODE>implements<\/CODE> template.<\/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-110889","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A closer look at the parameters to the <CODE>implements<\/CODE> template.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110889","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=110889"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110889\/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=110889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}