内部成员在课堂上的可见度

vso*_*tco 11 c++ language-lawyer

根据C++标准,

9.2 [class.mem]:

在类说明符的结束时,类被认为是完全定义的对象类型(3.9)(或完整类型).在类成员规范中,该类在函数体,缺省参数,引入继承构造函数(12.9)的使用声明,异常规范和非静态数据成员的括号或等于初始化器中被视为完整(包括嵌套类中的这类东西).否则,它在其自己的类成员规范中被视为不完整

所以,下面的代码应该编译,确实如此

struct Foo{
     Foo()
     {
        Bar bar; // Bar is fully visible here, even though it's defined later
     }
     //void f(Bar){} // But NOT VISIBLE if used as a function parameter
     struct Bar{};
};

int main()
{
    Foo foo;
}
Run Code Online (Sandbox Code Playgroud)

Live on Coliru

但是,如果我取消注释定义成员函数的行void Foo::f(Bar),则代码无法使用错误进行编译

错误:'Bar'尚未声明

确实再次阅读标准,似乎函数参数不被视为类被视为完整的地方.但是,它根本没有任何意义.你可以解释为什么我不能Bar在函数参数中使用它(但在其完全定义之前可以函数完全使用它而没有任何问题)?

Sha*_*our 6

9.2 [class.mem]中列出的所有情况中,知道类型可以延迟到完全定义类之前.我们可以在缺陷报告643中看到这个基本原理:在类成员规范中使用decltype,它说:

在类的定义中认为类类型完整的其他情况下,可以将处理构造推迟到定义的结尾.这对于类型是不可能的,因为在后续声明中可能需要立即使用类型.

正如TC指出的那样,还存在查找问题,因为缺陷报告325:何时解析默认参数?缺陷报告1352处理.后者还提到了能够推迟解析直到课程完成的相同技巧:

关于类范围的规则以及何时认为类是完整的(通常通过对类成员声明的部分进行延迟解析来实现)是不一致的,需要澄清.