bam*_*s53 10 c++ language-lawyer
我遇到了一些像这样的代码:
struct A {
A() {}
A(int) {}
};
struct B : A {
void init(int i);
};
void B::init(int i) {
A::A(i); // what is this?
}
int main() {
B b;
b.init(2);
}
Run Code Online (Sandbox Code Playgroud)
使用VC11 beta进行编译和运行,没有错误或警告/ W4.
明显的意图是调用B :: init重新初始化B的A基础子对象.我相信它实际上解析为一个名为itype 的新变量的变量声明A.使用clang进行编译会产生诊断:
ConsoleApplication1.cpp:11:14: warning: declaration shadows a local variable
A::A(i);
^
ConsoleApplication1.cpp:10:22: note: previous declaration is here
void B::init(int i) {
^
ConsoleApplication1.cpp:11:14: error: redefinition of 'i' with a different type
A::A(i);
^
ConsoleApplication1.cpp:10:22: note: previous definition is here
void B::init(int i) {
^
Run Code Online (Sandbox Code Playgroud)
好奇的是,类型可以用冗余类限定来引用.
此外,A::A(i)VS11和clang/gcc似乎对其进行了不同的解析.如果我做A::A(b)clang和gcc 使用默认构造函数创建一个b类型的变量A.VS11错误的说法b是一个未知的标识符.VS11似乎解析A::A(i)作为临时的创建A使用构造A::A(int)与i作为参数.当消除冗余限定符时,VS将源解析为类似clang和gcc do的变量声明,并产生关于隐藏变量的类似错误i.
解析的这种差异解释了为什么VS11会超过一个额外的限定符; A::A::A::A(i)以及为什么,鉴于clang和gcc可以接受一个额外的限定符,任何多于一个额外的数字都会产生与一个额外数字相同的结果.
这是另一个在不同上下文中使用冗余限定符的示例.所有编译器似乎都将其解析为临时构造:
class Foo {};
void bar(Foo const &) {}
int main() {
bar(Foo::Foo());
}
Run Code Online (Sandbox Code Playgroud)
class D : B { using B::B; };)的语法,但VS似乎允许它在任何地方.VS是错误的并且在如何解析冗余限定符时是否正确且是gcc?B b(A::A(i));clang和gcc作为最令人烦恼的解析解析的地方可能会更糟糕,但VS认为它是用初始化程序声明一个b类型的变量B.这种严重的差异还有很多吗?虽然这种现象很可能归因于类名注入,如ephemient的回答所指出的,对于这个具体的例子,它已经被C++语言禁止了很久以前.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#147
组合A::A需要引用类构造函数,而不是类注入名称.在A::A(i)假定由一个兼容的编译器为涉及构造名的非法的(并且因此没有意义)的表达来解释.例如,Comeau编译器将因此拒绝编译代码.
显然VC11继续将其A::A视为对注入的类名的引用.有趣的是,我在VS2005中没有观察到这个问题.
在A::A被解释为引用注入名称的那一天,可以将A对象声明为
A::A::A::A::A::A a;
Run Code Online (Sandbox Code Playgroud)
等等,任意数量的As.但不是了.令人惊讶的是,ideone使用的GCC版本(4.3.4?)仍然存在这个问题
您可以尝试使用您的VC11版本,看看它是否允许.