sed*_*iel 8 c++ construction temporary most-vexing-parse
最近我遇到了一个问题,不知何故(但只是某种程度上)对我有意义.它基于解释临时的构造作为单个(!)构造函数参数的声明.请看下面的最小例子.
#include <iostream>
class Foo0{
public:
Foo0(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo1{
public:
Foo1(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo2{
public:
Foo2(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Bar{
public:
Bar(Foo0 foo0, Foo1 foo1, Foo2 foo2){};
};
int main () {
int x = 1;
Bar bar0(Foo0(x), Foo1(x), Foo2(x)); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’; conflicting declaration ‘Foo2 x’ previous declaration as ‘Foo0 x’
Bar bar1(Foo0{x}, Foo1(x), Foo2(x)); // Works WTF
Bar bar2(Foo0(x), Foo1{x}, Foo2(x)); // Works WTF
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
Bar bar4(Foo0{x}, Foo1{x}, Foo2{x}); // Works totally makes sens to me
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious though.
}
Run Code Online (Sandbox Code Playgroud)
我已经读过这样的表达式:
Foo(a);
Run Code Online (Sandbox Code Playgroud)
被解释(如果有一个标准的构造函数)作为a的声明.这是有道理的,它完全没问题,因为你可以使用{} -brackets来明确构造结构.但我不明白的是:
为什么bar0的构造有问题?所有人Foo都没有标准的构造函数.所以解释像Foo0(x)声明这样的东西是没有意义的x.
为什么要建设 bar1和bar2工作?对我来说很明显是bar4作品的构造,因为我使用{} -brackets作为所有临时Foo的,因此我明确我想要的东西.
如果只需要使用{} -brackets只有一个 Foo s来解决问题...为什么构造bar3失败?
此外,在构造任何Bar之前声明x.为什么编译器不抱怨?
最后一个问题与我最后一行示例代码有关.长话短说:编译器认为我希望他做什么,我在哪里想念阴影的外观?
PS:如果感兴趣的话 - 我使用的是gcc-4.9.2.
PPS:我尝试使用bar三个Foo0s作为参数的构造函数.同样的故事在这里 但错误没有说明相互矛盾的声明,而是关于重新定义x.
M.M*_*M.M 10
规则是如果声明具有函数声明的语法,那么它就是一个; 否则它是一个变量声明.令人惊讶的例子有时被称为最令人烦恼的解析.
Bar bar0(Foo0(x), Foo1(x), Foo2(x)); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’; conflicting declaration ‘Foo2 x’ previous declaration as ‘Foo0 x’
Run Code Online (Sandbox Code Playgroud)
这是一个函数声明:bar0是名称,Bar是返回类型,参数类型是Foo0,Foo1和Foo2.参数名称都是x非法的 - 函数参数的名称必须不同.如果更改x x x到x y z错误消失).
Bar bar1(Foo0{x}, Foo1(x), Foo2(x)); // Works WTF
Bar bar2(Foo0(x), Foo1{x}, Foo2(x)); // Works WTF
Bar bar4(Foo0{x}, Foo1{x}, Foo2{x}); // Works totally makes sens to me
Run Code Online (Sandbox Code Playgroud)
这些行和创建对象bar1,bar2和bar4类型Bar.它们不能被解析为函数声明,因为{ }符号在函数声明中不是有效的语法.
因此,Foo0{x}等等是为Bar构造函数提供参数的表达式.Foo0{x}并且Foo0(x)是Foo0使用初始化程序声明临时类型的等效方法x.
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
Run Code Online (Sandbox Code Playgroud)
我认为这是一个编译错误; 该部分Foo2{x}意味着该行不能是函数声明; 它看起来像一个变量的有效声明bar3.
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious
Run Code Online (Sandbox Code Playgroud)
x是一个int; 它没有任何方法.