{"id":108057,"date":"2023-04-17T07:00:00","date_gmt":"2023-04-17T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108057"},"modified":"2023-04-16T21:15:47","modified_gmt":"2023-04-17T04:15:47","slug":"20230417-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230417-00\/?p=108057","title":{"rendered":"How can I find the invalid class when C++\/WinRT tells me that the class may not be final?"},"content":{"rendered":"<p>A customer was porting some C++\/CX code to C++\/WinRT and one of the things they did was change the nonstandard C++\/CX <code>sealed<\/code> keyword to the standard <code>final<\/code> keyword. They were a bit too aggressive about applying the <code>final<\/code> keyword, though, because they were getting this compiler error:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<th>File<\/th>\n<th>Line<\/th>\n<\/tr>\n<tr>\n<td>C2338<\/td>\n<td>C++\/WinRT implementation types must not be final<\/td>\n<td>base.h<\/td>\n<td>7759<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The customer wanted to know which class was the one that was erroneously declared as <code>final<\/code>. Can C++\/WinRT be improved so the error message includes the name of the bad type?<\/p>\n<p>Okay, so second question first.<\/p>\n<p>This error message is generated by a <code>static_assert<\/code>, and the rules for <code>static_assert<\/code> say that the message must be a string literal. It cannot be created dynamically. The error message is fixed; you can&#8217;t incorporate any compile-time information into it.<\/p>\n<p>However, not all is lost.<\/p>\n<p>If you look at the full error log, you can see that the compiler does tell you which class is the bad one:<\/p>\n<pre style=\"white-space: pre-wrap;\">base.h(7759,29): error C2338: C++\/WinRT implementation types must not be final\r\ncontoso.cpp(556): message : see reference to function template instantiation 'auto winrt::make&lt;winrt::<wbr \/>Contoso::<wbr \/>implementation::<wbr \/>Widget&gt;(void)' being compiled\r\n<\/pre>\n<p>This is a multi-line error message, but the Visual Studio error summary shows you only the first line. You have to flip to the Output window to see the second line, and that second line tells you where the problem is: The error message is coming from <code>make&lt;winrt::<wbr \/>Contoso::<wbr \/>implementation::<wbr \/>Widget&gt;<\/code>, and that gives you a strong clue that the problem is with <code>winrt::<wbr \/>Contoso::<wbr \/>implementation::<wbr \/>Widget<\/code>.<\/p>\n<p>You can also get the information by reading the <i>second<\/i> error message:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<th>File<\/th>\n<th>Line<\/th>\n<\/tr>\n<tr>\n<td>C3246<\/td>\n<td>&#8216;winrt::impl::heap_implements&lt;D&gt;&#8217;: cannot inherit from &#8216;<span style=\"border: solid 1px black;\">winrt::<wbr \/>Contoso::<wbr \/>implementation::<wbr \/>Widget<\/span>&#8216; as it has been declared as &#8216;final&#8217;<\/td>\n<td>base.h<\/td>\n<td>7685<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The full error text also tells you the identity of the bad base class:<\/p>\n<pre style=\"white-space: pre-wrap;\">base.h(7685,1): error C3246: 'winrt::impl::heap_implements&lt;D&gt;': cannot inherit from 'winrt::<wbr \/>Contoso::<wbr \/>implementation::<wbr \/>Widget' as it has been declared as 'final'\r\nwith\r\n[\r\n    D=Contoso::<wbr \/>implementation::<wbr \/>Widget\r\n]\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s in the error details.<\/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-108057","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s in the error details.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108057","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=108057"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108057\/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=108057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}