下面的代码无法编译。可能是因为带有 std=c++2a 的 GCC 仍然没有完全跟上最新的草案

The code below doesn't compile. Maybe because GCC with std=c++2a is still not completely up to date with the most recent draft

[class.mem]/6:

A complete-class context of a class is a

(6.1) function body, (6.2) default argument, (6.3) noexcept-specifier ([except.spec]), (6.4) contract condition, or (6.5) default member initializer

within the member-specification of the class. [ Note: A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class. — end note ]

本段是在带有拉取请求的草案中引入的 #2231

据我所知,根据上面的注释,下面的代码应该可以编译。但是it doesn't。我假设 GCC 编译器仍未与最新草案保持同步。我是正确的,还是我对这篇笔记的理解不正确?

struct A {
    int i = 1;
    struct B { 
        int j = 2;
        int f() {
            return i + j;
        }
    };
};

失败:

source>: In member function 'int A::B::f()':
<source>:6:20: error: invalid use of non-static data member 'A::i'
    6 |             return i + j;
      |                    ^
<source>:2:9: note: declared here
    2 |     int i = 1;
      |         ^

我认为这里的混淆源于 complete-class context 的要点是什么以及它打算如何使用。

重要的是,名称查找会在那里找到 i。所以我可以这样写:

struct A {
    struct B { 
        int j = 2;
        int f() {
            using T = decltype(i); // ok, even though 'i' declared later lexically
            return T{} + j;        // ok
        }
    };
    int i = 1;
};

以及:

struct A {
    struct B { 
        int j = 2;
        int f() {
            return i + j; // ok, even though 'i' declared later lexically
        }
    };
    static const int i = 1;
};

的确,这在 C++11 中一直没问题。

但是i仍然是一个非静态成员,所以你只能从A类型的对象的上下文中访问它。在 B 的成员函数体内,我们并没有隐式地拥有一个 A 对象。所以这样的免费使用 i 仍然是错误的。


也就是说,这个:

I'm assuming that the GCC compiler is still not up to date with the most recent draft.

肯定是真的,而且会在相当长的一段时间内保持真实。

Then what exactly is that note saying?

在 class A 中声明的名称在完整 class 上下文的范围内,即使在名称声明点之前也是如此。

注释表示封闭 class 的完整 -class 上下文(注意前置条件)扩展到嵌套 [=21] 的完整 -class 上下文=].

因此以下是合式的:

struct A {
    struct B{
        void foo() {
            // names are in scope despite being before point of declaration
            I i;
            var;
        }
    };

     using I = int;
     static int var;
};

您不能在另一个 class 的(非静态)成员函数中访问非静态数据成员,就像您不能在同一个 [=21] 的静态成员函数中访问非静态成员一样=].完整-class 上下文不会改变这一点。