{"id":109534,"date":"2024-03-14T07:00:00","date_gmt":"2024-03-14T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109534"},"modified":"2024-03-14T10:30:21","modified_gmt":"2024-03-14T17:30:21","slug":"20240314-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240314-00\/?p=109534","title":{"rendered":"How well does ATL <CODE>CComPtr<\/CODE> support class template argument deduction (CTAD)?"},"content":{"rendered":"<p>Continuing our investigation of <a title=\"Class template argument deduction (CTAD) and C++ COM wrappers, part 1: Initial explorations\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240311-00\/?p=109521\"> which C++ COM wrappers support class template argument deduction<\/a> (CTAD), next up is ATL&#8217;s <code>CComPtr<\/code>.<\/p>\n<p>ATL&#8217;s <code>CComPtr<\/code> works with CTAD right out of the box because the constructor that takes a pointer provides all the information needed to specialize the template class.<\/p>\n<pre>template &lt;class T&gt;\r\nclass CComPtr : public CComPtrBase&lt;T&gt;\r\n{\r\npublic:\r\n    CComPtr(_Inout_opt_ T* lp); \/\/ this constructor\r\n\r\n    \u27e6 other stuff \u27e7\r\n};\r\n\r\nvoid sample(Test* p)\r\n{\r\n    \/\/ Works right out of the box!\r\n    auto smart = CComPtr(p);\r\n}\r\n<\/pre>\n<p>The compiler sees that the constructor parameter is a <code>T*<\/code>, so it can figure out what <code>T<\/code> needs to be.<\/p>\n<p>Interestingly, but perhaps not surprisingly, it is the smart pointer class with the most straightforward constructor that works best with CTAD. CTAD tries to enable magic template arguments, and if you make your constructor too fancy, CTAD won&#8217;t be able to figure out what it needs to do.<\/p>\n<p>Next up is WRL, and things get more complicated.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It actually works right out of the box.<\/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-109534","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It actually works right out of the box.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109534","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=109534"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109534\/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=109534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}