{"id":111295,"date":"2025-06-23T07:00:00","date_gmt":"2025-06-23T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111295"},"modified":"2025-06-23T09:25:32","modified_gmt":"2025-06-23T16:25:32","slug":"20250623-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250623-00\/?p=111295","title":{"rendered":"The MIDL compiler still has trouble with double greater-than signs, sadly"},"content":{"rendered":"<p>The parser for the Microsoft MIDL compiler has long suffered from the problem of the double greater-than sign. This problem plagued C++ until C++11 added a special rule:\u00b9<\/p>\n<blockquote class=\"q\"><p><b>[temp.names]<\/b> (4): When parsing a <i>template-argument-list<\/i>, the first non-nested <tt>&gt;<\/tt> is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested <tt>&gt;&gt;<\/tt> is treated as two consecutive but distinct <tt>&gt;<\/tt> tokens, the first of which is taken as the end of the <i>template-argument-list<\/i> and completes the <i>template-id<\/i>.<\/p><\/blockquote>\n<p>Microsoft&#8217;s MIDL compiler predates C++11, and its parser treats two consecutive greater-than signs as a bitwise shift operator. This means that you cannot write<\/p>\n<pre>Windows.Foundation.IAsyncOperation&lt;\r\n    Windows.Foundation.Collections.IVector&lt;Int32<span style=\"border: solid 1px currentcolor;\">&gt;&gt;<\/span>\r\n<\/pre>\n<p>when you want an asynchronous operation that produces a vector of 32-bit integers. The double-greater-than is interpreted as a shift operator, and you get a weird MIDL error message because a shift operator is not allowed there.<\/p>\n<p>You must explicitly insert a space to force it to be parsed as two greater-than signs.<\/p>\n<pre>Windows.Foundation.IAsyncOperation&lt;\r\n    Windows.Foundation.Collections.IVector&lt;Int32<span style=\"border: solid 1px currentcolor;\">&gt; &gt;<\/span>\r\n<\/pre>\n<p>Larry Osterman tells me that multiple people have attempted to fix this and allow the compiler to break up a shift operator into two greater-than signs &#8220;when appropriate&#8221;.<\/p>\n<p>All such attempts have failed.<\/p>\n<p>I wonder if there is a comment in the source code <a href=\"https:\/\/stackoverflow.com\/questions\/184618\/what-is-the-best-comment-in-source-code-you-have-ever-encountered\/482129#482129\"> similar to this legendary one<\/a>:<\/p>\n<pre>\/\/ \r\n\/\/ Dear maintainer:\r\n\/\/ \r\n\/\/ Once you are done trying to 'optimize' this routine,\r\n\/\/ and have realized what a terrible mistake that was,\r\n\/\/ please increment the following counter as a warning\r\n\/\/ to the next guy:\r\n\/\/ \r\n\/\/ total_hours_wasted_here = 42\r\n\/\/ \r\n<\/pre>\n<p>\u00b9 The controversy is still not over, though, because the standard <a href=\"https:\/\/cplusplus.github.io\/CWG\/issues\/579.html\"> does not define what &#8220;non-nested&#8221; means<\/a>. Issue 579 gives as an example the sequence<\/p>\n<pre>X&lt;a ? b &gt; c : d&gt;\r\n<\/pre>\n<p>Is the first <tt>&gt;<\/tt> a &#8220;nested&#8221; greater-than sign? This issue, opened in 2006, is still outstanding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many have tried.<\/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":[2],"class_list":["post-111295","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Many have tried.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111295","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=111295"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111295\/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=111295"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111295"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111295"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}