Skip to content
Why is a raven like a writing desk?

Thoughts both confusing and enlightening.

Why is a raven like a writing desk?

Thoughts both confusing and enlightening.

Clang/GCC weirdness

elbeno, 5 February, 201530 June, 2015

Consider the following code:

#include 
#include 
using namespace std;

// base template
template 
struct what_type
{
  void operator()()
  {
    cout << "T" << endl;
  }
};

// specialization 1
template 
struct what_type
{
  void operator()()
  {
    cout << "T[" << N << "]" << endl;
  }
};

// specialization 2
template <>
struct what_type
{
  void operator()()
  {
    cout << "int[0]" << endl;
  }
};

int main(void)
{
  int x[] = {};
  what_type>()();

  return 0;
}

I compile this with GCC (g++ (Ubuntu 4.9.1-16ubuntu6) 4.9.1) and I get:

bdeane@epsilon:~/dev/scratch$ g++ -std=c++1y main.cpp 
bdeane@epsilon:~/dev/scratch$ ./a.out
T

When I use clang (Ubuntu clang version 3.5.0-4ubuntu2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)) I get:

bdeane@epsilon:~/dev/scratch$ clang++ -std=c++1y main.cpp 
bdeane@epsilon:~/dev/scratch$ ./a.out
int[0]

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. T).

If I put an assert in the base template member function, both clang and gcc think that T = int[0] and give almost identical messages:

a.out: main.cpp:53: void what_type<int [0]>::operator()() [T = int [0]]: Assertion `false' failed.

So why isn’t specialization 1 selected? (And it makes no difference either if I have a specialization for T[] as well as/instead of T[N].)

Edit:

Zero-sized arrays are illegal in C++, although GCC and Clang both compile them by default, presumably for historical reasons. If I turn on pedantic, both give me a warning.

From n4296 8.5.1 section 4:

An empty initializer list {} shall not be used as the initializer-clause for an array of unknown bound. (note 105)
105) The syntax provides for empty initializer-lists, but nonetheless C++ does not have zero length arrays.

So if GCC/Clang are going to allow zero-length arrays, I think they should be consistent about it and do specialization “correctly”. 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 “more” correct. I have yet to try with Clang/LLVM 3.6+.

Edit 2:

Clang 3.7 produces the same output as clang 3.5.

C++ Programming

Post navigation

Previous post
Next post

Related Posts

Formatted Diagnostics with C++20

10 December, 202410 December, 2024

C++26 adds formatted diagnostics with static_assert, something like this: The benefit of course is that when such an assertion fails, the compiler outputs a diagnostic that we control. But can this be done in C++20? Well, this is C++! So the answer is a qualified yes – we can get…

Read More

Approximating elliptical arcs with Bézier curves

29 March, 2008

In doing my modulation work with curves and ellipses, I extended the vecto function for drawing an ellipse to enable an oriented ellipse. Lately it occurred to me that this didn’t go far enough in terms of functionality, and I began wondering about how to draw part of an elliptical…

Read More

Monads are part of C++, and are in your code

19 September, 202219 September, 2022

For several reasons, I didn’t get a CppCon ticket this year, but since I live in the Denver metro area I did go on the Friday, which is free to attend. Herb’s closing keynote (Cpp2) was thought provoking. At one point though, he said, Think about the words and the…

Read More

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

©2026 Why is a raven like a writing desk? | WordPress Theme by SuperbThemes