{"id":103735,"date":"2020-05-08T06:47:52","date_gmt":"2020-05-08T13:47:52","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103735"},"modified":"2020-05-08T06:47:52","modified_gmt":"2020-05-08T13:47:52","slug":"20200508-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200508-52\/?p=103735","title":{"rendered":"The C++ preprocessor doesn&#8217;t understand anything about C++, and certainly not templates"},"content":{"rendered":"<p>The C and C++ preprocessors are like the Windows command prompt batch language: They implement a very simple language that people still use for some reason, usually by pushing it way beyond its original design boundaries.<\/p>\n<p>The preprocessors don&#8217;t really understand the C or C++ language. It does, fortunately, use the same arithmetic operators that the C and C++ language uses, but its understanding of them is limited to integers.<\/p>\n<p>The treatment of commas in preprocessor arguments is very simple: Commas separate macro arguments. The only way to protect a comma is to enclose it in matched parentheses.<\/p>\n<pre>#define M(cond, action) if (cond) action \/\/ horrible macro\r\n\r\nM(function(2, 3), return) \/\/ okay\r\n<\/pre>\n<p>Note that the less-than and greater-than signs do not protect commas. This can create confusion if you want to pass a template instantiation as a macro parameter.<\/p>\n<pre>M(std::is_same_v&lt;T, U&gt;, return); \/\/ doesn't compile\r\n<\/pre>\n<p>The preprocessor isn&#8217;t smart enough to realize that what you passed was intended to be a template instantiation. After all, maybe you wanted this:<\/p>\n<pre>M(value &lt; 0 || height &gt; 1000, return out_of_range);\r\n<\/pre>\n<p>In this case, the less-than and greater-than signs are intended to be the comparison operators. But from the preprocessor&#8217;s point of view, the angle brackets in<\/p>\n<pre>    std::is_same_v&lt; T, U &gt;\r\n<\/pre>\n<p>and<\/p>\n<pre>    value &lt; 0 || height &gt; 1000\r\n<\/pre>\n<p>are basically the same thing. It has no way of knowing that the first case of matched angle brackets is a template instantiation, whereas the second is just a pair of comparison operators. Not even the compiler knows, because we are still preprocessing. Compilation hasn&#8217;t happened yet.<\/p>\n<p>The solution is to insert seemingly-spurious parentheses around the macro argument.<\/p>\n<pre>M((std::is_same_v&lt;T, U&gt;), return);\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>You need to help it along.<\/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-103735","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You need to help it along.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103735","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=103735"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103735\/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=103735"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103735"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103735"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}