2
template < int ...Indices>

class T1 {
    template <int _1, int _2>
    class T2;
};

template <int ...Indices>
template <int _1>
class T1<Indices...>::T2<_1, sizeof...(Indices)> {};
//^--error: non-type template argument depends on a template parameter of the partial specialization

compiles on gcc 4.5+ but neither on clang 3.1 nor icc, both complaining about the usage of sizeof...(Indices). Is it just a not-yet implemented feature in the latter compilers or some special case?

Thanks,

Buote

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Buote Xu
  • 66
  • 3
  • 4
    Looks like a bug in those compilers. If you can, try defining the nested template inside `T1`'s `class {}` block, perhaps delegating to a separate member template if necessary. – Potatoswatter Jan 15 '12 at 12:20

2 Answers2

1

The standard says in [temp.class.spec] paragraph 8 that

Within the argument list of a class template partial specialization, the following restrictions apply:
— A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier. [ Example:

    template <int I, int J> struct A {};
    template <int I> struct A<I+5, I*2> {};  // error
template <int I, int J> struct B {}; template <int I> struct B<I, I> {}; // OK
end example ]

The purpose of the rule is to disallow partial specializations based on non-trivial expressions like those in the example, and sizeof...(Indices) is not a simple identifier so maybe clang and ICC are right to reject it. I'm not sure which compiler is right, to be honest. I suggest reporting a bug to one of the compilers and if they say their implementation is correct report it to the others for interpreting it differently!

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
0

You could attempt to try:

template < int ...Indices>
class T1 
{
    static const int index_size = sizeof...(Indices);

    template <int _1, int _2>
    class T2;
};

template <int ...Indices>
template <int _1>
class T1<Indices...>::T2<_1, T1<Indices...>::index_size> {};

and see if the compiler issue is with the actual sizeof... operator, or if it's with the way it's being used in the template declaration.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • That doesn't work either, so I guess they're both lacking the feature at the moment - as a workaround i just reversed my initial recursion order so that the partial specialization could be done for a constant value (e.g. 1). – Buote Xu Jan 17 '12 at 20:36
  • As a sidenote, the intel compiler has some weird issues sometimes with the specialization of nested classes - making the corresponding declaration necessary inside the outer class' `{};` block instead of outside. – Buote Xu Jan 17 '12 at 20:45