{"id":1005,"date":"2015-02-05T23:05:21","date_gmt":"2015-02-06T07:05:21","guid":{"rendered":"http:\/\/www.elbeno.com\/blog\/?p=1005"},"modified":"2015-06-30T21:16:56","modified_gmt":"2015-07-01T04:16:56","slug":"clanggcc-weirdness","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=1005","title":{"rendered":"Clang\/GCC weirdness"},"content":{"rendered":"<p>Consider the following code:<\/p>\n<pre lang=\"cpp\">\r\n#include <iostream>\r\n#include <type_traits>\r\nusing namespace std;\r\n\r\n\/\/ base template\r\ntemplate <typename T>\r\nstruct what_type\r\n{\r\n  void operator()()\r\n  {\r\n    cout << \"T\" << endl;\r\n  }\r\n};\r\n\r\n\/\/ specialization 1\r\ntemplate <typename T, size_t N>\r\nstruct what_type<T[N]>\r\n{\r\n  void operator()()\r\n  {\r\n    cout << \"T[\" << N << \"]\" << endl;\r\n  }\r\n};\r\n\r\n\/\/ specialization 2\r\ntemplate <>\r\nstruct what_type<int[0]>\r\n{\r\n  void operator()()\r\n  {\r\n    cout << \"int[0]\" << endl;\r\n  }\r\n};\r\n\r\nint main(void)\r\n{\r\n  int x[] = {};\r\n  what_type<std::remove_reference_t<decltype(x)>>()();\r\n\r\n  return 0;\r\n}\r\n<\/pre>\n<p>I compile this with GCC (g++ (Ubuntu 4.9.1-16ubuntu6) 4.9.1) and I get:<\/p>\n<pre lang=\"bash\">\r\nbdeane@epsilon:~\/dev\/scratch$ g++ -std=c++1y main.cpp \r\nbdeane@epsilon:~\/dev\/scratch$ .\/a.out\r\nT\r\n<\/pre>\n<p>When I use clang (Ubuntu clang version 3.5.0-4ubuntu2 (tags\/RELEASE_350\/final) (based on LLVM 3.5.0)) I get:<\/p>\n<pre lang=\"bash\">\r\nbdeane@epsilon:~\/dev\/scratch$ clang++ -std=c++1y main.cpp \r\nbdeane@epsilon:~\/dev\/scratch$ .\/a.out\r\nint[0]\r\n<\/pre>\n<p>It seems GCC is wrong here: I would expect specialization 2 to be selected. Now, if I remove specialization 2, clang gives the same output as GCC (i.e. <code>T<\/code>).<\/p>\n<p>If I put an assert in the base template member function, both clang and gcc think that <code>T = int[0]<\/code> and give almost identical messages:<\/p>\n<p><code>a.out: main.cpp:53: void what_type&lt;int [0]&gt;::operator()() [T = int [0]]: Assertion `false' failed.<\/code><\/p>\n<p>So why isn&#8217;t specialization 1 selected? (And it makes no difference either if I have a specialization for <code>T[]<\/code> as well as\/instead of <code>T[N]<\/code>.)<\/p>\n<p><em>Edit:<\/em><\/p>\n<p>Zero-sized arrays are illegal in C++, although GCC and Clang both compile them by default, presumably for historical reasons. If I turn on <code>pedantic<\/code>, both give me a warning.<\/p>\n<p>From <a href=\"https:\/\/github.com\/cplusplus\/draft\/blob\/master\/papers\/n4296.pdf\">n4296<\/a> 8.5.1 section 4:<\/p>\n<blockquote><p>An empty initializer list {} shall not be used as the <em>initializer-clause<\/em> for an array of unknown bound. (note 105)<br \/>\n105) The syntax provides for empty <em>initializer-list<\/em>s, but nonetheless C++ does not have zero length arrays.<\/p><\/blockquote>\n<p>So if GCC\/Clang are going to allow zero-length arrays, I think they should be consistent about it and do specialization &#8220;correctly&#8221;. A friend reports that Clang\/LLVM 3.3 does what GCC does here and uses the base template. Clang\/LLVM 3.5 uses specialization 2, which is &#8220;more&#8221; correct. I have yet to try with Clang\/LLVM 3.6+.<\/p>\n<p><em>Edit 2:<\/em><\/p>\n<p>Clang 3.7 produces the same output as clang 3.5.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Consider the following code: #include #include using namespace std; \/\/ base template template struct what_type { void operator()() { cout<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,8],"tags":[],"class_list":["post-1005","post","type-post","status-publish","format-standard","hentry","category-cpp","category-programming"],"_links":{"self":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1005","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1005"}],"version-history":[{"count":11,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1005\/revisions"}],"predecessor-version":[{"id":1017,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1005\/revisions\/1017"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}