Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this enum convert to int?

Tags:

c++

enums

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 
like image 903
Jim V Avatar asked Dec 01 '17 15:12

Jim V


People also ask

Can an enum be an integer?

No, we can have only strings as elements in an enumeration.

Can enum be treated as int?

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.

How do I assign an int to an enum?

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 .

Is enum always integer?

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.


2 Answers

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); 
like image 152
molbdnilo Avatar answered Sep 17 '22 15:09

molbdnilo


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.

like image 37
StaceyGirl Avatar answered Sep 18 '22 15:09

StaceyGirl