注入 class 名称编译器差异
Injected class name compiler discrepancy
考虑这段代码:
struct foo{};
int main() {
foo::foo a;
}
我希望它的格式正确,根据 [class]/2 中的规则声明类型 foo
的变量(N4140,强调我的):
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name.
clang 3.6.0
同意我的观点,使用 -Wall -pedantic
.
编译上述代码时没有适用的警告
gcc 5.2.0
不同意,提供以下错误信息:
main.cpp: In function 'int main()':
main.cpp:5:5: error: 'foo::foo' names the constructor, not the type
foo::foo a;
无论注入的 class 名称的嵌套有多深,以上内容都适用,例如foo::foo::foo::foo
.
是否存在强制将构造函数解释为该上下文中的构造函数的规则,或者这是一个gcc
错误?还是我对标准引用的解释不正确?
我认为这是language defect #147的主题
其中包含此示例
class B { };
class A: public B {
A::B ab; // B is the inherited injected B
A::A aa; // Error: A::A is the constructor
};
至少 gcc 似乎是这么认为的。 :-)
相关,但不是答案:GCC 人员确切地 讨论了这个 for years and figured that it should not be accepted. They explicitly made this an error in GCC 4.5 and newer - in 4.4.7 它被接受了。
顺便说一句:在调查此类内容时,您可能想使用 Clang 的 -Weverything
而不是 -Wall -pedantic
。
在这种情况下,clang
似乎是错误的。我正在寻找的相关例外是 [class.qual]/2:
2 In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C:
(2.1)
if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C, or
[...]
the name is instead considered to name the constructor of class C.
该标准有一个近乎等效的(显然是非规范的)示例:
struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba;// object of type A
A::A a;// error, A::A is not a type name
struct A::A a2;// object of type A
但是,clang
实际上在这种情况下发出了正确的诊断:
error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared
也许 clang
将行 In a lookup in which function names are not ignored
解释为 In a lookup in which a constructor declaration is valid
,但这似乎不是正确的解释。
在 clang
bugzilla 中有一个 existing bug。
考虑这段代码:
struct foo{};
int main() {
foo::foo a;
}
我希望它的格式正确,根据 [class]/2 中的规则声明类型 foo
的变量(N4140,强调我的):
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.
clang 3.6.0
同意我的观点,使用 -Wall -pedantic
.
gcc 5.2.0
不同意,提供以下错误信息:
main.cpp: In function 'int main()':
main.cpp:5:5: error: 'foo::foo' names the constructor, not the type
foo::foo a;
无论注入的 class 名称的嵌套有多深,以上内容都适用,例如foo::foo::foo::foo
.
是否存在强制将构造函数解释为该上下文中的构造函数的规则,或者这是一个gcc
错误?还是我对标准引用的解释不正确?
我认为这是language defect #147的主题 其中包含此示例
class B { };
class A: public B {
A::B ab; // B is the inherited injected B
A::A aa; // Error: A::A is the constructor
};
至少 gcc 似乎是这么认为的。 :-)
相关,但不是答案:GCC 人员确切地 讨论了这个 for years and figured that it should not be accepted. They explicitly made this an error in GCC 4.5 and newer - in 4.4.7 它被接受了。
顺便说一句:在调查此类内容时,您可能想使用 Clang 的 -Weverything
而不是 -Wall -pedantic
。
在这种情况下,clang
似乎是错误的。我正在寻找的相关例外是 [class.qual]/2:
2 In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C:
(2.1) if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C, or
[...]
the name is instead considered to name the constructor of class C.
该标准有一个近乎等效的(显然是非规范的)示例:
struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba;// object of type A
A::A a;// error, A::A is not a type name
struct A::A a2;// object of type A
但是,clang
实际上在这种情况下发出了正确的诊断:
error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared
也许 clang
将行 In a lookup in which function names are not ignored
解释为 In a lookup in which a constructor declaration is valid
,但这似乎不是正确的解释。
在 clang
bugzilla 中有一个 existing bug。