C++ 是我对'这个词的解释;第一';在§;3.3.2/6是否正确?

C++ 是我对'这个词的解释;第一';在§;3.3.2/6是否正确?,c++,c++11,language-lawyer,C++,C++11,Language Lawyer,在下面的片段中,我可以理解(从§3.3.2/6第二个要点)声明中的名称B作为类名注入全局命名空间 §3.3.2/6: 类的声明点首先在 详细的类型说明符如下所示: 申请表格的声明 类键属性说明符seq opt identifier 标识符被声明为作用域中的类名 包含声明,否则为 对于窗体的详细类型说明符 类密钥标识符 如果在命名空间范围中定义的函数的decl说明符seq或参数声明子句中使用了详细的类型说明符,则该标识符将声明为 包含声明的命名空间中的类名;否则,除非作为朋友声明,否则标识符为

在下面的片段中,我可以理解(从§3.3.2/6第二个要点)声明中的名称
B
作为类名注入全局命名空间

§3.3.2/6:

类的声明点首先在 详细的类型说明符如下所示:

  • 申请表格的声明

    类键属性说明符seq opt identifier

    标识符被声明为作用域中的类名 包含声明,否则为

  • 对于窗体的详细类型说明符

    类密钥标识符

    如果在命名空间范围中定义的函数的decl说明符seq或参数声明子句中使用了详细的类型说明符,则该标识符将声明为 包含声明的命名空间中的类名;否则,除非作为朋友声明,否则标识符为 在包含 宣言。[注:这些规则也适用于模板。-结束 注][注:其他形式的详细类型说明符不适用 声明新名称,因此必须引用现有类型名称。 见3.4.4和7.1.6.3.-结束注释]

但是,如果我取消注释
structb{}的定义
struct A
中,我前面提到的关于将name
B
注入全局名称空间的内容不再出现,因为代码不会编译。我相信这与上面的单词first(强调我的)有关,因为现在在声明
结构B*p中的类名
B
不再是其声明区域中的第一个声明。我这样说对吗

假设我的解释是正确的,那么在这种情况下,为什么没有将类名
B
注入全局名称空间?注意,嵌套类
structb{}将隐藏在A中,即,即使我们将函数
f
的声明更改为
void f(A::B&)
代码也不会编译


还有一点我还不清楚:是什么让实现者在上面的第二个要点中决定将类名注入包含详细类型说明符的命名空间或块范围?也就是说,他们为什么不将类名声明留在类范围内?

我认为您的解释是正确的。当您取消注释
struct B{},结构B*p行将简单地引用该结构
A::B

回答你的问题为什么,当你离开
structb{}注释掉,名称
结构B
插入全局范围。我想说,这是因为作者不希望你(有点)在没有使用成员规范的情况下,默默地宣布
B
a
的成员
B
你是对的,§3.3.2/6中的第一个关键字也是以下原因:

struct A {
    struct B *p;
    struct B{};
    int b;
};

void f(B* arg) {
    std::cout << std::is_same<decltype(arg), A::B*>::value; // not the same type
}

int main()
{
    A a;
    f(a.p);
}
结构A{ 结构B*p; 结构B{}; int b; }; 无效f(B*arg){
std::cout对封闭名称空间的注入肯定是为了与C兼容。您能进一步探讨一下吗?C没有类/结构范围,因此,
struct S{struct X{int y;};int X;};struct X my_var={42};
在C中是合法的(呃,这很难看——但它实际上是用clang和gcc编译的,尽管后者中有一个警告)。答案很好,但我相信上面@dyp给出的例子更能说明在第二个要点3.3.2/6(+1)中提出的类名注入方面与C的间接兼容性。
struct A {
    struct B *p;
    struct B{};
    int b;
};

void f(B* arg) {
    std::cout << std::is_same<decltype(arg), A::B*>::value; // not the same type
}

int main()
{
    A a;
    f(a.p);
}