使用后声明
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
C++20 标准草案 N4861 节。 6.5.1(7) 读取:
A name used in the definition of a class
X
outside of a complete-class context ofX
shall be declared ... before its use in classX
or be a member of a base class ofX
....
那么为什么下面的编译?
#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