成员的结构与命名空间的潜在范围

Member's potential scope for struct vs namespace

参考这段代码:

namespace Y {
  char f() { return y; } // error: y was not declared in this scope
  char y;
}

struct X {
  char  f() { return x; } // OK
  char  x;
};

根据basic.scope.namespace#1

The declarative region of a namespace-definition is its namespace-body. Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. Its potential scope includes its namespace from the name's point of declaration onwards.

问题

  1. 错误是由于 Y::y 尚未在 Y::f() 中声明吗?

  2. 我不明白为什么 namespace 成员在声明期间没有 "reodering" 而 [=14] =] 有。禁止这种行为的原因可能是什么? 标准是否有类似的说法?

Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?

是的。

I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?

与 classes 相比,命名空间的最大障碍是它们永远不是 "closed"。您始终可以通过在另一个翻译单元中重新打开命名空间并在其中声明更多内容来将成员添加到命名空间。但是,对于其所有成员,class 声明必须完全出现在单个翻译单元中。以后也不会再添加了。

[class.mem]/1

The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.

命名空间的问题很棘手。但是 classes 只需要多一点,非常本地化的工作。

因此,对于语言设计者和编译器编写者来说,要求命名空间声明在使用之前出现要容易得多。

您还应注意,您只能在定义内的一组特定位置使用 class 的其他成员。

[class.mem]/6

A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

你误以为结构有 "reordering".

考虑以下结构定义。

#include <iostream>

struct A
{
    char s[N];
    enum { N = 10 };
};

int main() 
{
    return 0;
}

编译器会报错,因为名称N在数组声明中使用时尚未声明。因此 "reordering" 都不存在于 class 范围内。至于成员函数,则首先在 class 范围内搜索成员函数中使用的名称。

此外,在命名空间中声明的名称可以隐藏在外部命名空间中声明的相同名称。结果 "reordering" 打破了变量的范围。