In the following code
#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;
}
all compilers I tested agree the code (un-commented version) is invalid but I fail to see why the definition
P2d lp(<double>, <double>);
that I used is not acceptable.
I remember the rule was "if it can be both a function declaration and a definition then it's a declaration" but I expected that if it cannot be a declaration then it should be interpreted as a definition instead of giving an error.
What am I missing?
Hold on to your chair since it's pretty funny. As you surely know C++ allows array function parameters. And so you can get this:
void foo(double s[2], double b[2]);
This is obvious. A possible obfuscation step is to replace spaces between type and parameters name which is also allowed:
void foo(double(s[2]),double(b[2]));
Now you can imagine what can be done pretty simply - replace numbers with const char*
. Like this:
void foo(double(s["x"]),double(b["y"]));
This is invalid function declaration, nevertheless it is seen by the compilers as exactly this - declaration. This is exactly what happened to your code.
EDIT:
The whole problem seems to arise from not strict enough restrictions on array declarators in C++ standard. The only requirement for array 'size' parameter is being constexpr
value which is supposed to be converted to std::size_t
(but it is not checked on the level of syntax analysis, it is done later on). For more on that check this