Nested class explicit specilization: different compiler behavior
Asked Answered
L

1

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?

Lowney answered 23/4, 2018 at 15:38 Comment(0)
I
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.

Ingold answered 24/4, 2018 at 18:19 Comment(9)
Hmm. Thank you for your reference! But void A<int>::B<char>::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?Lowney
@Lowney The wording might itself use vague English language, but the intent is clear. See my example and comment.Ingold
I mean it looks like a lack of an exact wording for this case in the standard (including an exact example for it).Lowney
@Lowney 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.Ingold
The latter rule isn't applicable in this case, it is clear. But I'm not sure the former one is applicable.Lowney
@Lowney 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.Ingold
OK, thank you. So there is no problem that two semantically different definitions have the same syntax (see the cases 1 and 2), isn't it?Lowney
@Lowney I don't really see what's so different there, but no, evidently not.Ingold
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.Lowney

© 2022 - 2024 — McMap. All rights reserved.