以下代码无法按预期编译:
#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 ++对模板成员函数有不同的访问规则来访问嵌套类?
答案 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?
~~~^
答案 1 :(得分:3)
这不是海湾合作委员会的错误。您不调用函数模板,因此该函数未实例化,并且它不会尝试访问嵌套类的私有成员。尝试在真实函数(不是模板)中调用函数或尝试引用它(隐式实例化)。
函数模板本身不是类型,函数或任何其他实体。不包含仅包含模板定义的源文件的代码。为了显示任何代码,必须实例化模板:必须确定模板参数,以便编译器可以从类模板生成实际函数(或类)。
当代码引用上下文中需要存在函数定义的函数时,并且此特定函数尚未显式实例化,则会发生隐式实例化。
template void Enclosing::EnclosingFun(Enclosing::Nested *n, int t); // instantiates the function for the second int parameter