使用后声明

Declaration after use

C++20 标准草案 N4861 节。 6.5.1(7) 读取:

A name used in the definition of a class X outside of a complete-class context of X shall be declared ... before its use in class X or be a member of a base class of X....

那么为什么下面的编译?

#include <iostream>
  
struct X {
    X(const int i_) : i(i_) {}
    int f() const { return 3*g(); }
    int g() const { return 2*i; }
    const int i;
};

int main()
{
    const X x{7};
    std::cout << x.f() << "\n";
}

我的意思是,当然,它确实应该编译,并且确实编译了,并且输出 42 正如人们所期望的那样;但我不明白标准的措辞。该标准说,“在使用之前”,但在示例中,g() 不是在 使用后 声明的吗?还有i

简短的回答是您没有违反引用的规则。

据我了解,关键部分是“在完整的 class 上下文之外”。我看到你在f()中使用了g()g()还没有正式声明,但是在classX中。如果 g() 是在 X 之后声明和实现的全局函数,我认为这就是您 运行 遇到问题的地方。如果 class X 有一个成员 Y 对象,编译器需要首先了解 Y 的所有信息,以便可以包含它。这就是规则的意思。

您引用的段落的关键部分是

outside of a complete-class context

在成员函数体内,您处于完整的 class 上下文中。这意味着该规则不适用。

完整的class contect 的完整定义可以在[class.mem.general]/7:

中找到

A complete-class context of a class (template) is a

  • function body ([dcl.fct.def.general]),
  • default argument ([dcl.fct.default]),
  • default template argument ([temp.param]), noexcept-specifier ([except.spec]), or
  • default member initializer