{"id":109521,"date":"2024-03-11T07:00:00","date_gmt":"2024-03-11T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109521"},"modified":"2024-03-11T09:51:54","modified_gmt":"2024-03-11T16:51:54","slug":"20240311-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240311-00\/?p=109521","title":{"rendered":"Class template argument deduction (CTAD) and C++ COM wrappers: Initial explorations"},"content":{"rendered":"<p>A while back, we studied the duck typing requirements of C++ COM wrappers and <a title=\"Summary of the duck-typing requirements of C++ COM wrappers\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230516-00\/?p=108192\"> summarized them in a table<\/a>. Today we&#8217;ll look at a smaller point of comparison: Class template argument deduction, also known as CTAD, introduced in C++17.<\/p>\n<p>CTAD lets you omit the <code>&lt;...&gt;<\/code> arguments of a class template under certain circumstances. For example, you can write<\/p>\n<pre>auto v = std::vector({ 1, 2, 3 });\r\n<\/pre>\n<p>instead of<\/p>\n<pre>auto v = std::vector<span style=\"border: solid 1px currentcolor;\">&lt;int&gt;<\/span>({ 1, 2, 3 });\r\n<\/pre>\n<p>You may even have been using this feature without realizing it:<\/p>\n<pre>auto lock1 = std::lock_guard(m_mutex1);\r\nstd::lock_guard lock2(m_mutex2);\r\n<\/pre>\n<p>These are shorthand for<\/p>\n<pre>auto lock1 = std::lock_guard<span style=\"border: solid 1px currentcolor;\">&lt;std::mutex&gt;<\/span>(m_mutex1);\r\nstd::lock_guard<span style=\"border: solid 1px currentcolor;\">&lt;std::mutex&gt;<\/span>( lock2(m_mutex2);\r\n<\/pre>\n<p>For C++ COM wrappers, a common pattern is constructing a smart pointer from a raw pointer. Let&#8217;s see how well these wrapper classes handle CTAD.<\/p>\n<pre>IWidget* p;\r\n\r\n\/\/ _com_ptr_t: nope\r\nauto smart = _com_ptr_t(p); \/\/ does not compile\r\n\r\n\/\/ MFC IPTR\/CIP: nope\r\nauto smart = CIP(p); \/\/ does not compile\r\nauto smart = CIP(p, TRUE); \/\/ does not compile\r\n\r\n\/\/ ATL CComPtr: yes\r\nauto smart = CComPtr(p); \/\/ deduces CComPtr&lt;IWidget&gt;\r\n\r\n\/\/ WRL ComPtr: nope\r\nauto smart = ComPtr(p): \/\/ does not compile\r\n\r\n\/\/ wil com_ptr: maybe\r\nauto smart = wil::com_ptr(p); \/\/ requires C++20\r\n\r\n\/\/ C++\/WinRT com_ptr: nope\r\nauto smart = winrt::com_ptr(p); \/\/ does not compile\r\n<\/pre>\n<p>Note that these tests are unfair, because all of these libraries predate C++17!<\/p>\n<p>We&#8217;ll spend the next few days looking at why CTAD doesn&#8217;t work, how the library authors could have supported CTAD (had they known about it), and what we as library consumers can do about it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How well do these libraries support a feature that likely didn&#8217;t exist at the time they were written?<\/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-109521","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>How well do these libraries support a feature that likely didn&#8217;t exist at the time they were written?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109521","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=109521"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109521\/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=109521"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109521"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109521"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}