为什么内联声明不是不完整的类型?

vso*_*tco 14 c++ incomplete-type

请考虑以下代码:

struct Foo {
    struct Bar;
    Foo()
    {
        Bar bar; // Why isn't Bar an incomplete type?!
    }
    struct Bar {}; // Full definition
};

// struct Bar {}; // fails to compile due to incomplete type

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

它在至少2个编译器(gcc5.2,clang3.5)下编译得很好.我的问题是:

  • 为什么Bar在构造函数中不被认为是不完整的类型Foo::Foo,因为我将它在构造函数上方转发声明但在构造函数中完全使用它?

每当我走出Foo::Bar课堂之外,换句话说,Bar成为一个独立的课程,我得到了预期

错误:聚合'Foo :: Bar bar'的类型不完整,无法定义

Sha*_*our 8

在成员规范中,从C++标准草案9.2 [class.mem]草案中,该类在函数体中被认为是完整的:

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

这意味着你甚至不必转发声明Bar(见它直播):

struct Foo {
    Foo()
    {
        Bar bar; 
    }
    struct Bar {};  
};
Run Code Online (Sandbox Code Playgroud)

前瞻性声明可能有助于避免违反第3.3.7第2和第3款.