下面的代码无法编译。可能是因为带有 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
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 上下文不会改变这一点。
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 上下文不会改变这一点。