g++ Bug with Partial Template Specialization

c++, c++11, template-aliases, template-specialization, templates

Solution

This seems like a g++ bug because clearly `foo<B, B, extents>` is more specialized than `foo<A, B, extents>` (te latter can match anything that the former matches, but not vice versa), so the compiler should choose that specialization.

As you noted yourself, changing `extents` from a template alias to a class template, solves the problem.

Problem

I am writing some TMP-heavy code for g++ (version 4.8.1_1, Macports) and clang++ (version 3.3, Macports). While g++ rejects the following code listing with UNBRIDLED FURY, clang++ compiles it with grace and splendor. - Which complier is in the right? (I strongly suspect it's g++, but I want to get some reassurance from others before submitting a bug report.) - Do you have any easy or elegant workarounds to suggest? (I need to use template aliases, so switching over to structs, which causes g++ to accept the code, is not an option.) Here is the code listing, made just for you. ``` template <class... Ts> struct sequence; template <int T> struct integer; // This definition of `extents` causes g++ to issue a compile-time error. template <int... Ts> using extents = sequence<integer<Ts>...>; // However, this definition works without any problems. // template <int... Ts> // struct extents; template <int A, int B, class Current> struct foo; template <int A, int B, int... Ts> struct foo<A, B, extents<Ts...>> { using type = int; }; template <int B, int... Ts> struct foo<B, B, extents<Ts...>> { using type = int; }; int main() { using t = foo<1, 1, extents<>>::type; return 0; } ``` Here is g++'s output: ``` er.cpp: In function 'int main()': er.cpp:39:41: error: ambiguous class template instantiation for 'struct foo<1, 1, sequence<> >' using t = typename foo<1, 1, extents<>>::type; ^ er.cpp:26:8: error: candidates are: struct foo<A, B, sequence<integer<Ts>...> > struct foo<A, B, extents<Ts...>> ^ er.cpp:32:8: error: struct foo<B, B, sequence<integer<Ts>...> > struct foo<B, B, extents<Ts...>> ^ er.cpp:39:43: error: 'type' in 'struct foo<1, 1, sequence<> >' does not name a type using t = typename foo<1, 1, extents<>>::type; ^ ``` Here is clang++'s output: Thanks for your help!

Original source