C++ class 模板函数可以访问嵌套的 class 私有成员

C++ class template function can access nested class private member

以下代码无法按预期编译:

#include<iostream>
class Enclosing {
    int x;
    class Nested { int y; };

    void EnclosingFun(Nested *n) {
        std::cout << n->y;  // Compiler Error: y is private in Nested
    }
};

但是,如果我将 EnclosingFun 更改为模板成员函数,编译器 (gcc-7) 不会抱怨访问 y:

#include<iostream>
class Enclosing {      
    int x;
    class Nested { int y; };

    template <typename T>
    void EnclosingFun(Nested *n, T t) {
        std::cout << t << n->y;  // OK? Why?
    }      
};

这是 gcc 中的错误吗?或者 c++ 是否有不同的模板成员函数访问规则来访问嵌套的 类?

Is this a bug in gcc? Or does c++ have different access rules for template member function to access nested classes?

也没有。

按照标准,§17.8.1 Implicit instantiation [temp.inst],

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.

也就是说,Enclosing::EnclosingFun()这里没有实例化。向它添加调用会导致它被实例化,然后你会得到错误,例如

prog.cc:8:30: error: 'int Enclosing::Nested::y' is private within this context
         std::cout << t << n->y;  // OK? Why?
                           ~~~^

LIVE

这不是 GCC 中的错误。你没有调用你的函数模板,因此函数没有被实例化,它也没有尝试访问嵌套 class 的私有成员。尝试在真实函数(而非模板)中的某处调用您的函数或尝试引用它(隐式实例化)。

A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function (or class, from a class template).

When code refers to a function in context that requires the function definition to exist, and this particular function has not been explicitly instantiated, implicit instantiation occurs.

template void Enclosing::EnclosingFun(Enclosing::Nested *n, int t); // instantiates the function for the second int parameter