I have some compiler behavior - different on VisualC++ and g++ - that I don't understand (for either compiler). I will describe it in English but maybe it would be easier just to look at the code below.
It has to do with a class template that has a member class template and a member function template. I am trying to simultaneously
- Explicitly specialize the outer class template (leaving the member templates unspecialized)
- Explicitly specialize the member templates within the explicit specialization of the outer class template.
I find that, with both compilers, everything compiles fine (and instantiations are as expected) if I do either #1 (explicitly specialize outer class template) or #2 (explicitly specialize member templates).
But if I try to do both #1 and #2 simultaneously (declared in the correct order I believe), I find that
- With g++, I can do this for the member class template, but get a compiler error for the member template class declaration.
- For VC++, I get compiler errors for both member templates.
Here is the outer class template primary definition. It is the same in all of the cases below:
// Class template with a member class template and a member function template
template <int I>
struct OuterClass
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
Here is doing #1 (explicitly specialize outer class template) only. This compiles fine and instantiations are as expected.
// Explicit specialization of outer class template,
// leaving member templates unspecialized.
template <>
struct OuterClass<1>
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
Here is doing #2 (explicitly specialize member templates) only. This compiles fine and instantiations are as expected.
// Explicit specialization of inner templates for
// an explicit specialization of outer class template
template <> template <> struct OuterClass<1>::InnerClass<1> {};
template <> template <> void OuterClass<1>::InnerFunc<1>() {}
Here is trying to do both #1 and #2 simultaneously - just pasting the two previous code snippets together:
// Explicit specialization of outer class template,
// leaving member templates unspecialized.
template <>
struct OuterClass<1>
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
// Explicit specialization of inner templates for
// an explicit specialization of outer class template
template <> template <> struct OuterClass<1>::InnerClass<1> {}; // Line A
template <> template <> void OuterClass<1>::InnerFunc<1>() {} // Line B
g++ compiles "Line A" fine (and instantiations are as expected). But g++ gives a compiler error for Line B: "too many template-parameter-lists".
VC++ gives compiler errors for both "Line A" and "Line B" (too messy and numerous to recount here).
Again, both "Line A" and "Line B" compile fine, for both compilers, when they do not appear after the explicit specialization of the outer class template.
In my understanding, everything should compile fine. So who is right - me, g++, or VC++? And more importantly, why?
Please understand this is not a "How do I accomplish X" question, this is a "I want to fully understand C++" question. If you take the time to read through this and think about it you have my thanks...I hope I boiled it down as much as possible.