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 Error instance does not resolve.
class Error { public: Error(int err) : code_(err) {} const int code_; }; enum Value { value_1 }; int main() { // compiles Error e(value_1); // does not compile under G++, ARM, or MSVC Error(value_1); }
Example error under G++: (Coliru link)
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()': main.cpp:19:18: error: no matching function for call to 'Error::Error()' Error(value_1); ^ main.cpp:4:5: note: candidate: Error::Error(int) Error(int err) : code_(err) {} ^~~~~ main.cpp:4:5: note: candidate expects 1 argument, 0 provided main.cpp:1:7: note: candidate: constexpr Error::Error(const Error&) class Error ^~~~~ main.cpp:1:7: note: candidate expects 1 argument, 0 provided main.cpp:1:7: note: candidate: constexpr Error::Error(Error&&) main.cpp:1:7: note: candidate expects 1 argument, 0 provided
No, we can have only strings as elements in an enumeration.
An Enum value cannot be treated as an int by default because then you would be able to provide any integer and there would be no compile time check to validate that the provided integer does in fact exist as a value in the Enumeration.
The correct syntax to use type casting is as follows. Copy YourEnum variableName = (YourEnum)yourInt; The program below shows how we can use the type casting to cast an int to enum in C#. We have cast our integer value to enum constant One .
In ANSI C, the expressions that define the value of an enumerator constant always have int type. That means the storage associated with an enumeration variable is the storage required for a single int value.
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);
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With