Why does the following code not compile under g++ (C++14), MSVC (C++14), or ARM (C++03)?
The named Error instance calls the integer constructor, but the anonymous Er
This comes from the same place as "The Most Vexing Parse" - the rule that if it can be a declaration, it is a declaration.
And surprisingly, you're allowed to put parentheses around the identifier in a variable declaration.
(I have no idea why, but I'm guessing that it simplified C's parser back in the day.)
The following are all valid declarations of int
variables:
int (foo);
int (bar) = 0;
int (baz)(3);
int (twaddle)(baz);
main.cpp:19:18: error: no matching function for call to 'Error::Error()'
Error(value_1);
The compiler tries to call the non-existent default constructor Error::Error()
because it sees
Error(value_1);
as a variable declaration
Error value_1;
A declaration is allowed to have redundant parenthesis.
The problem is that code
Error(value_1);
is a declaration of a variable value_1
of type Error
.
This is a legacy from C language that uses expressions as part of type declaration.
For example int *i
is a pointer to int
because it says that expression *i
should evaluate to type int
. More examples of this:
int (*func)()
is a pointer to function returning int
because expression (*func)()
evaluates to type int
.int *p[8]
is an array of pointers to int
because expression *p[x]
evaluates to type int
.int (*p)[8]
is a pointer to array of 8 int
's (int[8]
) because expression (*p)[x]
evaluates to type int
.int (*(*p[8])())()
is an array of 8 pointers to functions returning pointers to a function returning int
because expression (*(*p[x])())()
evaluates to type int
.Similarly int (i)
is a plain variable of type int
as expression (i)
evaluates to type int
.
And so because C++ inherits this from C, it uses parenthesis as part of type declaration, but also adds more syntax on top, leading to some unexpected results.
The rule applied by C++ here says to treat everything that can be a declaration as a declaration.
Similar confusion if often caused by code like this:
Error ec();
which is a forward declaration of a function ec
that returns Error
.