最烦人的解析更烦人
Most vexing parse even more vexing
在下面的代码中
#include <map>
#include <string>
struct P2d {
double x, y;
P2d(double x, double y) : x(x), y(y) {}
};
double bar() {
std::map<std::string, int> m;
//P2d lp = P2d(double(m["x"]), double(m["y"])); // this works
P2d lp(double(m["x"]), double(m["y"]));
return lp.x;
}
我测试的所有编译器都同意代码(未注释版本)无效,但我不明白为什么定义
P2d lp(<double>, <double>);
我用的是不行的
我记得规则是“如果它既可以是函数声明又可以是定义,那么它就是一个声明”,但我希望如果它不能是一个声明,那么它应该被解释为一个定义而不是给出错误.
我错过了什么?
抓住你的椅子,因为它很有趣。正如您肯定知道的那样,C++ 允许数组函数参数。所以你可以得到这个:
void foo(double s[2], double b[2]);
这是显而易见的。一个可能的混淆步骤是替换类型和参数名称之间的空格,这也是允许的:
void foo(double(s[2]),double(b[2]));
现在您可以想象可以非常简单地完成什么 - 用 const char*
替换数字。像这样:
void foo(double(s["x"]),double(b["y"]));
这是无效的函数声明,但编译器认为它正是这个 - 声明。这正是您的代码所发生的情况。
编辑:
整个问题似乎是由于 C++ 标准中对数组声明符的限制不够严格。数组 'size' 参数的唯一要求是 constexpr
应该转换为 std::size_t
的值(但未在语法分析级别检查,稍后完成) .有关该检查的更多信息 this
在下面的代码中
#include <map>
#include <string>
struct P2d {
double x, y;
P2d(double x, double y) : x(x), y(y) {}
};
double bar() {
std::map<std::string, int> m;
//P2d lp = P2d(double(m["x"]), double(m["y"])); // this works
P2d lp(double(m["x"]), double(m["y"]));
return lp.x;
}
我测试的所有编译器都同意代码(未注释版本)无效,但我不明白为什么定义
P2d lp(<double>, <double>);
我用的是不行的
我记得规则是“如果它既可以是函数声明又可以是定义,那么它就是一个声明”,但我希望如果它不能是一个声明,那么它应该被解释为一个定义而不是给出错误.
我错过了什么?
抓住你的椅子,因为它很有趣。正如您肯定知道的那样,C++ 允许数组函数参数。所以你可以得到这个:
void foo(double s[2], double b[2]);
这是显而易见的。一个可能的混淆步骤是替换类型和参数名称之间的空格,这也是允许的:
void foo(double(s[2]),double(b[2]));
现在您可以想象可以非常简单地完成什么 - 用 const char*
替换数字。像这样:
void foo(double(s["x"]),double(b["y"]));
这是无效的函数声明,但编译器认为它正是这个 - 声明。这正是您的代码所发生的情况。
编辑:
整个问题似乎是由于 C++ 标准中对数组声明符的限制不够严格。数组 'size' 参数的唯一要求是 constexpr
应该转换为 std::size_t
的值(但未在语法分析级别检查,稍后完成) .有关该检查的更多信息 this