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

Webular lisp

9 October, 2007

I’ve decided to pick up the reins of lisp again and see if I can’t make some lispy web goodness. So to that end, I installed apache2, mod_lisp2, and did an asdf-install of cl-modlisp tonight. It seems to be correctly installed: next step is to go back to Practical Common…

Read More

Exercising Ranges (part 1)

1 July, 20151 July, 2015

The idea For some time since attending C++Now, I have been meaning to get around to playing with Eric Niebler’s range library. Eric presented ranges in a worked example as one of the keynotes at C++Now – a prior version of the talk that he gave at the Northwest C++…

Read More

C++ Tuples: the missing functionality

6 April, 201530 June, 2015

C++ provides a strange mix of compile-time and runtime functionality for dealing with tuples. There are some interesting parts, like std::tie to destructure a tuple, and std::tuple_cat to join together several tuples into one. So there is evidence that the standard has been influenced by some functional programming ideas, but…

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