The following source code is brought from: Understanding partial specialization of inherited nested class templates
#include <type_traits>
struct Base
{
template<class U, class _ = void> struct Inner: std::true_type {};
template<class _> struct Inner<char, _>: std::false_type {};
};
struct Derived : Base
{
};
template<class _> struct Derived::Inner<int, _>: std::false_type {};
I had an issue about specializing inherited class, so I googled, and find out the question above. The source code in the question above compiled w/o any problem in gcc/clang, but msvc refuses to compile it, issuing C2427 (see https://msdn.microsoft.com/en-us/library/10het5hx.aspx).
Situation of the above (specialize the nested template class of a non-template class) is quite different from the situation described in https://msdn.microsoft.com/en-us/library/10het5hx.aspx (define the nested non-template class of a template class), I think.
Which one of msvc vs. gcc/clang is wrong? Or just the standard is so unclear to specify this behavior?
I hope msvc is wrong...
Clang and GCC are wrong, and MSVC and EDG are right to reject that partial specialization definition.
A partial specialization is itself a template, and a class template definition is syntactically constructed in terms of a class definition (in grammar terms, a class-specifier). Within such a definition,
Derived::Inner<int, _>
is a class-head-name, withDerived::
being a nested-name-specifier.[9p11] in the Standard says:
So, you have to use
Base::Inner<int, _>
.As noted in the comments, the quote above applies to class template explicit specialization definitions as well (their grammar production also ends up using class-head-name).
The following doesn't apply directly to your example, but I found it worth mentioning.
Note that the quote above refers to class template (or explicit specialization) definitions, not declarations such as
Syntactically,
struct Derived::Inner<int, _>
in there is an elaborated-type-specifier, to which the paragraph above doesn't apply. So, the Standard wording technically allows such declarations.This doesn't seem to be an oversight: the wording above was introduced by the resolution of DR284, which includes the comment:
The proposed resolution included elaborated-type-specifiers, but those were removed from the final wording.
However, neither MSVC nor EDG accept such declarations (and frankly I'd find it confusing if they did). The comment in the DR seems to indicate that the intent was to allow only elaborated-type-specifiers that are not also declarations, but it looks like this wasn't reflected in the wording (a Standard bug, I think).