c++ - 我对 §3.3.2/6 中的单词 'first' 的解释是否正确?

标签 c++ c++11 language-lawyer

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

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

void f(B&) {}

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

§3.3.2/6:

The point of declaration of a class first declared in an elaborated-type-specifier is as follows:

  • for a declaration of the form

    class-key attribute-specifier-seq opt identifier;

    the identifier is declared to be a class-name in the scope that contains the declaration, otherwise

  • for an elaborated-type-specifier of the form

    class-key identifier

    if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration. [ Note: These rules also apply within templates. — end note ] [ Note: Other forms of elaborated-type-specifier do not declare a new name, and therefore must refer to an existing type-name. See 3.4.4 and 7.1.6.3. — end note ]

但是,如果我取消注释 struct Astruct B{}; 的定义,我之前所说的关于注入(inject)名称 B 进入全局命名空间,不再发生,因为代码无法编译。我相信这与上面的单词 first(强调我的)有关,因为现在 class-name B,在声明 struct B* p; 不再是它的第一个声明在其声明区域。我这样说对吗?

假设我的解释是正确的,为什么在这种情况下 class-name B 没有被注入(inject)全局命名空间?请注意,在这种情况下,嵌套类 struct B{}; 将隐藏在 A 中,即,即使我们将函数 f 的声明更改为 void f (A::B&) 代码无法编译。

还有一点我不太清楚:是什么让实现者决定在第二个要点中将类名注入(inject)到包含详细类型说明符的命名空间或 block 作用域中多于?也就是说,为什么他们不将类名声明留在类范围内?

最佳答案

你是对的,§3.3.2/6 中的 first 关键字也是以下原因:

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);
}

why is it that the class-name B is not injected in the global namespace in this case?

正如 dyp 指出的那样,[basic.lookup.elab]/2 解释说 3.3.2 仅在找不到以前的声明

的情况下执行

If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name, or if the elaborated-type-specifier appears in a declaration with the form:

class-key attribute-specifier-seqopt identifier ;

elaborated-type-specifier is a declaration that introduces the class-name as described in 3.3.2.the

最后我追踪到这种行为可能是从 C99 6.7.2.3/p8 继承而来

If a type specifier of the form

struct-or-union identifier

occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type.113)

113) A similar construction with enum does not exist.

关于c++ - 我对 §3.3.2/6 中的单词 'first' 的解释是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26168445/

相关文章:

c++ - 错误 : My every function & variable 'was not declared in this scope (code;;blocks, C++)

c++ - 通过运行时索引访问派生类中基类的成员

C++ 错误 : deduced conflicting types for parameter 'T' string vs const char *

c++ - 如何计算 N 个有序集的交集?

c++ - 如何在 C++ 中正确访问映射内存而没有未定义的行为

c++ - 我如何从另一个项目运行一个类?

c++ - 什么时候调用右值析构函数/这样可以吗

c++ - c++11 中的 boost::variant 和多态性

c++ - 声明但不定义未使用的函数是否合法?

c++ - 这两个说法在N4140中不是不兼容吗?