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

时间:2018-03-11 03:32:51

标签: 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
    }
};

但是,如果我将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 ++对模板成员函数有不同的访问规则来访问嵌套类?

2 个答案:

答案 0 :(得分:5)

  

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

没有。

根据标准,§17.8.1 Implicit instantiation [temp.inst]

  

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

这意味着Enclosing::EnclosingFun()未在此处实例化。将调用添加到它将导致它被实例化,然后您将得到错误,例如

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

LIVE

答案 1 :(得分:3)

这不是海湾合作委员会的错误。您不调用函数模板,因此该函数未实例化,并且它不会尝试访问嵌套类的私有成员。尝试在真实函数(不是模板)中调用函数或尝试引用它(隐式实例化)。

  

函数模板本身不是类型,函数或任何其他实体。不包含仅包含模板定义的源文件的代码。为了显示任何代码,必须实例化模板:必须确定模板参数,以便编译器可以从类模板生成实际函数(或类)。

     

当代码引用上下文中需要存在函数定义的函数时,并且此特定函数尚未显式实例化,则会发生隐式实例化。

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