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

Jon*_*gle 3 c++ templates private instantiation

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

#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
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,如果我将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?
    }      
};
Run Code Online (Sandbox Code Playgroud)

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

son*_*yao 5

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

也没有.

根据标准,§17.8.1隐式实例化[temp.inst],

实现不应隐式实例化函数模板,变量模板,成员模板,非虚拟成员函数,成员类,类模板的静态数据成员或constexpr if语句的子语句([stmt.如果]),除非需要这样的实例化.

这意味着,Enclosing::EnclosingFun()这里没有实例化.将调用添加到它将导致它被实例化,然后你将得到错误,例如

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

生活

  • 这实际上非常有用.例如,如果我正在编写`std :: vector <T>`,如果`T`没有默认构造函数,`resize`不起作用.幸运的是,我可以像`T`一样编写`resize`,只要用户不使用`resize`代码就会编译 (2认同)