[temp.spec]/6 was added to C++20 by implementation of P0692R1 (Access Checking on Specialization) [emphasis mine]:
[temp.spec]/6 The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer. [ Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects that would normally not be accessible. — end note ]
which, afaict, would make the following program well-formed as of C++20:
class A { class B {}; };
template<typename T> void foo() {};
template<> void foo<A::B>() {}
int main() {}
However, both GCC (HEAD 11.0.0 20201121; DEMO) and Clang (HEAD 12.0.0; DEMO) rejects the program above (for -std=c++20/-std=c++2a), citing an private access violation
GCC:
'class A::B' is private within this contextClang:
error: 'B' is a private member of 'A'
GCC lists P0692R1 as implemented:
whereas Clang lists its implementation of P0692R1 as Partial:
Question
- What is the correct behaviour in C++20 here, is the program above well-formed (GCC bug / Clang not fully implemented) or are GCC and Clang correct to reject it?