{"id":109546,"date":"2024-03-18T14:50:30","date_gmt":"2024-03-18T21:50:30","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109546"},"modified":"2024-03-18T14:50:30","modified_gmt":"2024-03-18T21:50:30","slug":"how-well-does-wil-com_ptr-support-class-template-argument-deduction-ctad","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240318-30\/?p=109546","title":{"rendered":"How well does wil <CODE>com_ptr<\/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 the Windows Implementation Library&#8217;s <code>wil::<wbr \/>com_ptr<\/code>.<\/p>\n<p>The wil <code>com_ptr<\/code> fails CTAD through no fault of its own.<\/p>\n<pre>template&lt;typename T, typename err_policy = err_exception_policy&gt;\r\nclass com_ptr_t\r\n{\r\npublic:\r\n    using pointer = T*;\r\n\r\n    com_ptr_t(pointer ptr) WI_NOEXCEPT; \/\/ this constructor\r\n\r\n    \u27e6 other stuff \u27e7\r\n};\r\n\r\ntemplate&lt;typename T&gt;\r\nusing com_ptr = com_ptr_t&lt;T, err_exception_policy&gt;;\r\n\r\n<\/pre>\n<p>The problem is that <code>wil::<wbr \/>com_ptr<\/code> is an alias template, and in C++17, alias templates could not participate in CTAD. This hole was <a title=\"Filling holes in Class Template Argument Deduction\" href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2019\/p1021r4.html\"> filled in by C++20<\/a>, so at least in C++20, you can say<\/p>\n<pre>Widget* p;\r\nauto smart = wil::com_ptr(p); \/\/ requires C++20\r\n<\/pre>\n<p>If you are stuck with C++17, then deduction guides won&#8217;t help, since C++17 disallows them on alias templates. (Seeing as alias templates couldn&#8217;t participate in CTAD in the first place, there&#8217;s no point letting you specify a deduction guide for something that canot be deduced in the first place.)<\/p>\n<p>Therefore, if you can&#8217;t use C++20, you&#8217;ll have to make do with a maker function.<\/p>\n<pre>template&lt;typename T&gt;\r\nwil::com_ptr&lt;T&gt; make_com_ptr(T* p)\r\n{\r\n    return p;\r\n}\r\n\r\ntemplate&lt;typename T&gt;\r\nwil::com_ptr_nothrow&lt;T&gt; make_com_ptr_nothrow(T* p)\r\n{\r\n    return p;\r\n}\r\ntemplate&lt;typename T&gt;\r\nwil::com_ptr_failfast&lt;T&gt; make_com_ptr_failfast(T* p)\r\n{\r\n    return p;\r\n}\r\n<\/pre>\n<p>Fortunately, wil comes with these maker functions already, so everything is ready for you.<\/p>\n<p>Next time, we&#8217;ll wrap up this mini-series on C++ COM wrappers and CTAD by looking at C++\/WinRT.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Falling into a hole in the C++ language, not filled in until C++20.<\/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-109546","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Falling into a hole in the C++ language, not filled in until C++20.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109546","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=109546"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109546\/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=109546"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109546"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109546"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}