【问题标题】:Declaration after use使用后声明
【发布时间】:2021-06-03 07:58:24
【问题描述】:

C++20 标准草案N4861 sect。 6.5.1(7) 内容如下:

在类 X 的定义中使用的名称 X 的完整类上下文应在使用之前声明... 类X 或成为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

【问题讨论】:

  • 你的例子没有违反你引用的规则。
  • @sweenish 是的,谢谢,我相信你是对的;但我不明白措辞。你想解释一下吗?
  • struct X { ... }; 是一个完整的类上下文
  • 据我了解,关键部分是“在完整类上下文之外”。我看到您在f() 中使用了g(),而g() 尚未正式声明,但它在X 类中。如果g() X 之后声明和实现的全局函数,我认为这就是您遇到问题的地方。如果类X 有一个成员Y 对象,那么编译器首先需要知道关于Y 的所有信息,以便将它包含在内。这就是规则所说的。
  • @RichardCritten 啊哈。显然,标准对形容词“完整”的使用让我感到困惑。如果您想让您的评论成为答案,我很乐意投票。

标签: c++ standards name-lookup


【解决方案1】:

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

在完整类上下文之外

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

完整类contect的完整定义见[class.mem.general]/7

一个类(模板)的完整类上下文是一个

  • 函数体([dcl.fct.def.general]),
  • 默认参数([dcl.fct.default]),
  • 默认模板参数([temp.param]), noexcept 说明符 ([except.spec]),或
  • 默认成员初始化器

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 误读评论。我会把它留给理查德发布答案。
    • 请留下您的答案。不要删除。很有帮助。
    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 2022-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-04-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多