在类中的定义之前分析声明

Parsing declarations before definitions in a class

本文关键字:声明 定义      更新时间:2023-10-16

这个问题在这里激起了我的兴趣。C++标准中是否有任何地方指定在成员函数的任何随附实现之前必须解析类中的所有声明?我看到了其他一些与此类似的问题,但在任何答案中都没有提及该标准。

标准没有指定编译器应如何解析翻译单元。相反,它指定了使用任何标识符来引用声明的所有位置以及无效的位置。

3.3.2p5:

在类成员的声明点之后,可以在其范围内查找成员名称 类。 [ 注意:即使类是不完整的类,也是如此。

3.3.7p1:

以下规则描述类中声明的名称的范围。

  1. 在类中声明的名称的潜在作用域不仅包括名称声明点后面的声明性区域,还包括所有函数体、非静态数据成员的大括号或等于初始值设定项以及该类中的默认参数(包括嵌套类中的此类内容)。
  2. N中使用的名称S应在其上下文中引用相同的声明,并在已完成的S范围内重新评估时。对于违反此规则,无需进行诊断。
  3. 如果对类中的成员声明重新排序在 (1) 和 (2) 下生成备用有效程序,则程序格式不正确,不需要诊断。
  4. 在成员函数
  5. 中声明的名称隐藏其作用域扩展到或超过成员函数类末尾的相同名称的声明。
  6. 扩展到
  7. 类定义末尾或超过类定义末尾的声明的潜在范围也会扩展到其成员定义定义的区域,即使成员在类之外以词法方式定义(这包括静态数据成员定义、嵌套类定义、成员函数定义(包括成员函数体和此类定义中此类定义中遵循声明符 id 的任何部分),包括参数声明子句和任何默认参数 (8.3.6)。

[class.mem] 说:

-2- 类在类说明符的结束}被视为完全定义的对象类型 (3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数和非静态数据成员(包括嵌套类中的此类内容)的大括号或等于初始值设定项中被视为完整。否则,它在其自己的类成员规范中被视为不完整。

为了使类在函数体内完成,那么通常需要解析所有声明:如果不完全解析所有声明,您将无法知道未解析的内容是否会改变含义。 虽然,可能与此相关的是[basic.scope.class]/1,它说:

3) 如果对类中的成员声明重新排序会产生 (1) 和 (2) 下的备用有效程序,则程序格式不正确,不需要诊断。

这意味着可以在不解析整个类的情况下使用某些声明,因为如果另一个后来的声明改变了含义,那么程序的格式将不正确。

当然,"好像"规则允许编译器选择任何实现,只要用户无法分辨出区别,所以也许编译器可以选择解析函数体,然后根据需要解析定义,但很难说处理成员函数定义需要什么(考虑一个可能调用几个重载函数之一的函数调用, 可能涉及enable_if型技巧。

这是

解释编程语言标准的草案C++。

编程语言 C++ PDF

我认为第 220 页对成员函数有一些解释。