gpt4 book ai didi

c++ - 带有前向声明的嵌套类在 clang++ 中导致错误,但在 g++ 上没有警告地通过

转载 作者:行者123 更新时间:2023-12-03 10:04:06 24 4
gpt4 key购买 nike

我试图结合嵌套类和前向声明来保持代码清晰,即使它有一个非常复杂的类结构。前向声明允许我减少此处的缩进级别。
以下代码在 g++-9.3 和 clang++-10 上编译得很好:

class A {
public:
class B;
};
class A::B {
public:
int foo=0;
};
但是,当我在另一个类中嵌套执行相同的操作时,此构造在 g++ 上没有任何警告地工作,但在 clang++ 上失败:
class Outer {
public:
class A {
public:
class B;
};
class A::B {
public:
int foo=0;
};
};
clang++ 的失败是:
test.cpp:7:16: error: non-friend class member 'B' cannot have a qualified name
class A::B {
~~~^
1 error generated.
我想这在某种程度上是无效的代码,gcc 足够仁慈以正确解释?我意识到我可以直接在类 A 中移动类定义,但假设我想保留这个版本的前向声明。

最佳答案

类头名称包含嵌套名称说明符的类说明符不能出现在类中;仅在封闭的命名空间内
来自 [class]/11 :

If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.


在你失败的例子中, A::是嵌套名称说明符和 A::B { ... }是类说明符。标准

[...] the class-specifier shall appear in a namespace enclosing the previous declaration.


不满足。特别要注意的是,类说明符包含类头,类头又包含类头名称,而类头名称又包含可选的嵌套名称说明符,以及(非可选的)类-姓名。如果存在嵌套名称说明符,则 [class]/11 适用,在这种情况下(如上所述)允许使用类说明符的要求适用;特别是,不允许嵌套在类中。
因此,您的程序格式错误;叮当是对的。

我们可能会注意到,如果 B 的类说明符,Clang 会接受该程序。出现在命名空间范围内(包含之前的类内声明):
class Outer {
public:
class A {
public:
class B;
};
};

class Outer::A::B {
public:
int foo=0;
};

最后,请注意 [class.nest]/3提到在声明它们的类的类中定义嵌套类,以及在封闭命名空间的命名空间范围内:

If class X is defined in a namespace scope, a nested class Y maybe declared in class X and later defined in the definition of classX or be later defined in a namespace scope enclosing the definitionof class X. [_ Example:_

 class E {   class I1;       // forward declaration of nested class  
class I2; class I1 { }; // definition of nested class }; class
E::I2 { }; // definition of nested class

— end example ]


这允许你的第一个例子:
class A {
public:
class B;
};
class A::B {
public:
int foo=0;
};

被重新分解为
class A {
public:
class B {
public:
int foo=0;
};
};
或者
class A {
public:
class B; // forward declaration
// ...
class B {
public:
int foo=0;
};
};
但是这里与 [class]/11 没有冲突,它专门管理当类头名称包含嵌套名称说明符时允许的语法。

关于c++ - 带有前向声明的嵌套类在 clang++ 中导致错误,但在 g++ 上没有警告地通过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64895983/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com