c++ - 下面的代码无法编译。可能是因为带有 std=c++2a 的 GCC 仍然没有完全跟上最新的草案

标签 c++ language-lawyer c++20

[class.mem]/6 :

A complete-class context of a class is a

(6.1) function body, (6.2) default argument, (6.3) noexcept-specifier ([except.spec]), (6.4) contract condition, or (6.5) default member initializer

within the member-specification of the class. [ Note: A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class. — end note ]

这一段是在带有pull-request的草案中引入的#2231 .

据我所知,根据上面的注释,下面的代码应该可以编译。但是it doesn't .我假设 GCC 编译器仍未与最新草案保持同步。我是正确的,还是我对这篇笔记的理解不正确?

struct A {
    int i = 1;
    struct B { 
        int j = 2;
        int f() {
            return i + j;
        }
    };
};

失败的是:

source>: In member function 'int A::B::f()':
<source>:6:20: error: invalid use of non-static data member 'A::i'
    6 |             return i + j;
      |                    ^
<source>:2:9: note: declared here
    2 |     int i = 1;
      |         ^

最佳答案

我认为这里的混淆源于完整类上下文的意义以及它打算如何使用。

重要的是,名称查找会在那里找到i。所以我可以这样写:

struct A {
    struct B { 
        int j = 2;
        int f() {
            using T = decltype(i); // ok, even though 'i' declared later lexically
            return T{} + j;        // ok
        }
    };
    int i = 1;
};

还有:

struct A {
    struct B { 
        int j = 2;
        int f() {
            return i + j; // ok, even though 'i' declared later lexically
        }
    };
    static const int i = 1;
};

的确,这在 C++11 中一直没问题。

但是 i 仍然是一个非静态成员,因此您只能从类型为 A 的对象的上下文中访问它。在 B 的成员函数体内,我们并没有隐含地拥有一个 A 对象。所以这样免费使用 i 仍然是错误的。


也就是说,这个:

I'm assuming that the GCC compiler is still not up to date with the most recent draft.

肯定是真的,而且会在相当长的一段时间内保持真实。

关于c++ - 下面的代码无法编译。可能是因为带有 std=c++2a 的 GCC 仍然没有完全跟上最新的草案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54696050/

相关文章:

c++ - 使用临时存储区 : is it allowed? 复制可简单复制的类型

c++ - 为什么在 C++ 标准库中没有定义 inv_sqrt2?

C++20 概念 : Which template specialization gets chosen when the template argument qualifies for multiple concepts?

c++ - 使用多维 std::initializer_list

c++ - 覆盖 `istream operator>>` 与使用 `sscanf`

c++ - 在 HtmlHelp 调用中使用 HelpId

c++ - 条件运算符 + upcast + const 引用

c++ - 为什么可变说明符被分类为存储类说明符,而不是限定符?

c++ - 使用 decltype 显式调用析构函数

c++ - 需要特定参数包大小的C++模板概念