为什么在显式实例化中不恰当地访问私有部分是合法的?

Dav*_*vid 11 c++ templates private access-specifier language-lawyer

为什么允许这样做:

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
template<typename T>
struct invisible
{
    static typename T::type value;
};

template<typename T>
typename T::type invisible<T>::value;

//////////////////////////////////////////////////////////////////////////
template<typename T, typename T::type P>
class construct_invisible
{
    construct_invisible(){ invisible<T>::value = P; }
    static const construct_invisible instance;
};

template<typename T, typename T::type P>
const construct_invisible<T, P> construct_invisible<T, P>::instance;

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class A
{
public:
    A(int x) : m_X(x){}
private:
    int m_X;
};

//////////////////////////////////////////////////////////////////////////
struct A_x{ typedef int A::*type; };
template class construct_invisible<A_x, &A::m_X>;// <---- WHY DOES `&A::m_X` WORK HERE?

//////////////////////////////////////////////////////////////////////////
int main()
{
    A a(17);
    std::cout << a.*invisible<A_x>::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)

幸得约翰内斯·绍布对于上述C++滥用.(演示)

是否还有其他情况可以访问您应该看不到的内容?这只是标准中的"错误"吗?

Joh*_*itb 4

这样,具有私有成员的类的作者就可以显式实例化该成员或将其作为参数传递,就像您刚才所做的那样。

编译器不知道谁在键盘前面,因此这里的访问检查相当保守。

显式实例化中使用的参数得到特殊处理,因为类作者没有机制可以在允许的上下文中显式实例化模板,或者以某种方式允许通过友元声明这样做。