[temp.spec]/6通过 P0692R1 的实现添加到 C++20 (特化访问检查)[ 重点 矿]:
[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 ]
事实上,这将使以下程序在 C++20 中形成良好的格式:
class A { class B {}; };
template<typename T> void foo() {};
template<> void foo<A::B>() {}
int main() {}
然而,GCC (HEAD 11.0.0 20201121; DEMO ) 和 Clang (HEAD 12.0.0; DEMO ) 都拒绝上述程序(因为 -std=c++20
/-std=c++2a
引用私有(private)访问)GCC:
'class A::B' is private within this context
Clang:
error: 'B' is a private member of 'A'
GCC 将 P0692R1 列为已实现:
而 Clang 将其 P0692R1 的实现列为部分:
题
最佳答案
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?
正如 OP 中已经引用的那样,[temp.spec]/6 支持此功能,并且程序格式良好。特别是,下面的所有片段 (A) 到 (D) 都是格式良好的:
// (A)
class A { class B {}; };
template<typename T> struct S {};
template<> struct S<A::B> {};
// (B)
class A { class B {}; };
template<typename T> void foo() {};
template<> void foo<A::B>() {}
// (C)
class A { class B {}; };
template<typename T>
constexpr bool v = false;
template<>
constexpr bool v<A::B> = true;
// (D)
class A { class B {}; };
template<typename T, typename U> struct S {};
template<typename U> struct S<A::B, U> {};
template<typename T> struct S<T, A::B> {};
GCC 错误地拒绝(B)和(C)(正确接受(A)和(D)),而 Clang 错误(1)拒绝(B)到(D)(正确接受(A))。错误报告:
(1) 请注意,Clang(在 OP 中突出显示)已将 P0692R1 的实现状态标记为“部分”,因此这可能不是 Clang 错误,而是尚未实现的功能 C++2a/C++20 .
关于c++ - 放弃 C++20 中显式函数模板特化的访问检查规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64960135/