9

The following code compiles fine with clang++ 6.0.0 and g++ 7.3.0 (compilation flags are -std=c++14 -Wall -Wextra -Werror -pedantic-errors) but fails to compile with vc++ 19.10.25017 (compilation flag is /Za):

template <typename>
struct A
{
    template <typename>
    struct B
    {
    };
};

template <>
template <>
struct A<int>::B<char>
{
    static void foo();
};

void A<int>::B<char>::foo()
{
}

int main()
{
}

vc++ compilation error message:

error C2906: 'void A<int>::B<char>::foo(void)': explicit specialization requires 'template <>'

What behavior is standard compliant in this case?

Constructor
  • 7,273
  • 2
  • 24
  • 66

1 Answers1

4

VC++ is wrong. Potentially misapprehending the following clause:

Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class (*). However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.

The intent of the latter rule is to disambiguate:

// Which template does this header appertain to?
template<class U> void A<short>::C<U>::f() { /* ... */ } 

However, in your case, the (*) case applies.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Hmm. Thank you for your reference! But `void A::B::foo()` isn't a simple member of an explicitly specialized class template in this case. It is a member of an explicitly specialized member class template that is specialized as a class template explicit specialization, isn't it? – Constructor Apr 24 '18 at 18:40
  • @Constructor The wording might itself use vague English language, but the intent is clear. See my example and comment. – Columbo Apr 24 '18 at 18:42
  • I mean it looks like a lack of an exact wording for this case in the standard (including an exact example for it). – Constructor Apr 24 '18 at 18:45
  • @Constructor No, some things are clear enough and need to be considered in context. This rule is meant to differentiate between "no template header required" and "some template header required". The fact that you're defining a member of nested specializations isn't interesting. – Columbo Apr 24 '18 at 18:47
  • The latter rule *isn't* applicable in this case, it is clear. But I'm not sure the former one *is* applicable. – Constructor Apr 24 '18 at 18:49
  • @Constructor The committee is aware that some rules, particularly regarding name lookup, don't deal with nesting properly. The wording must be interpreted with that in mind. – Columbo Apr 24 '18 at 18:50
  • OK, thank you. So there is no problem that [two semantically different definitions have the same syntax](http://coliru.stacked-crooked.com/a/d5f15f1de8acfeae) (see the cases 1 and 2), isn't it? – Constructor Apr 24 '18 at 18:58
  • @Constructor I don't really see what's so different there, but no, evidently not. – Columbo Apr 24 '18 at 19:04
  • The first one is a definition of a member of an explicitly specialized member class template that is specialized as a class template explicit specialization. The second one is a member of an explicit specialization of a member class template that is a member of a class template explicit specialization. – Constructor Apr 24 '18 at 19:10