Why do people use enums in C++ as constants while they can use const?
Solution 1
An enumeration implies a set of related constants, so the added information about the relationship must be useful in their model of the problem at hand.
Solution 2
Bruce Eckel gives a reason in Thinking in C++:
In older versions of C++,
static const
was not supported inside classes. This meant thatconst
was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untaggedenum
with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:
#include <iostream> using namespace std; class Bunch { enum { size = 1000 }; int i[size]; }; int main() { cout << "sizeof(Bunch) = " << sizeof(Bunch) << ", sizeof(i[1000]) = " << sizeof(int[1000]) << endl; }
Solution 3
There's a historical reason too when dealing with template metaprogramming. Some compilers could use values from an enum, but not a static const int to instantiate a class.
template <int N>
struct foo
{
enum { Value = foo<N-1>::Value + N };
};
template <>
struct foo<0>
{
enum { Value = 0; }
};
Now you can do it the more sensible way:
template <int N>
struct foo
{
static const int Value = foo<N-1>::Value + N;
};
template <>
struct foo<0>
{
static const int Value = 0;
};
Another possible reason, is that a static const int may have memory reserved for it at runtime, whereas an enum is never going to have an actual memory location reserved for it, and will be dealt at compile time. See this related question.
Solution 4
I like the automatic behavior that can be used with enums, for example:
enum {NONE, START, HEY, HO, LAST};
Then it is easy to loop until LAST, and when a new state (or whatever is represented) is added, the logic adapts.
for (int i = NONE; i < LAST; i++)
{
// Do stuff...
}
Add something...
enum {NONE, START, HEY, WEE, HO, LAST};
The loop adapts...
Solution 5
Enums are more descriptive when used. Consider:
int f(int fg, int bg)
versus
int f(COLOR fg, COLOR bg)
In addition, enums give a bit more type-safety, because
- integers are not implicitly convertible to enum types
- enum of one type is not implicitly convertible to enum of another type
Comments
-
Loai Abdelhalim about 3 years
Why do people use enums in C++ as constants when they can use
const
? -
ASk almost 15 yearsenum is an integral type, I don't believe it can store a constant such as Pi without significant loss of precision :)
-
ASk almost 15 yearsNon-static constants can't be initialized that way. I believe you meant "static const int Val1". Also, there are drawbacks in using this method of in-class initialization - the symbol for Val1 is not guaranteed to be created.
-
dss539 almost 15 yearsthey might store 314159 and just div by 10^5 every time :P hopefully the example gives the right idea about what I meant by global constants, however.
-
Loai Abdelhalim almost 15 yearsIt's not the only reason. Also, there's no big difference in typing.
-
Jan Hudec almost 13 yearsHm, that does not look like an answer to the question (though it was accepted). People use enums where they could use
const
and the values are not related. Often you'll seeenum { SOMETHING = 2232; }
(like that; unnamed enum with one value only) instead ofconst int SOMETHING = 2232;
. It's because enum never gets any storage while const variable is still a variable and will get (static) storage if the compiler can't proove it won't need one, which it often can't. -
Jan Hudec almost 13 years@ASk: The problem is the symbol for "static const int Val1" is not guaranteed to not be generated, so the programmer uses enum instead, because that does not create symbol at all.
-
motiz88 over 10 yearsThis is an old thread, but the two statements at the end of this answer are false and need correcting.
-
motiz88 over 10 years"integers are not implicitly convertible to enum types" and "enum of one type is not implicitly convertible to enum of another type" - false. Plain
enum
s will silently convert to/from integers, in C++ as in C. So they strictly don't provide this safety. However, in C++11, there isenum class
which is a proper C++ style "re-imagining" ofenum
: The implicit conversions are gone, and additionally value names must always be qualified. This is similar to C#enum
s, and avoids the name collision / namespace pollution issues that arise with C's oldenum
. -
weberc2 almost 10 years
typedef int my_new_fangled_type; void foo(my_new_fangled_type bar);
Problem solved, no enum needed, and I can change the memory representation by replacingtypedef int
withtypedef uchar
or some such. :) -
Jon Watte over 7 yearsAnother reason is that "const" POD variables are a newer C++ feature, and a lot of older code bases (and programmers who prefer the higher compatibility) still exist.
-
cosimo193 almost 7 years@motiz88 - I think you may be getting confused on this one. Try this code on gcc (you'll need to reformat it yourself): int main() { enum MyEnum1 { VAL11, VAL12, VAL13 }; enum MyEnum2 { VAL21, VAL22, VAL23, VAL24 }; int int1 = VAL11; MyEnum1 enum1 = 3; MyEnum2 enum2 = VAL11; enum2 = enum1; int int2 = enum1; return 0; } Enum values do implicitly convert to integers, but not vice-versa, and "enum types" don't implicitly convert between each other. In principle I believe ASk is correct here, but I don't think it's actually an answer to the op's question!
-
cosimo193 almost 7 yearsUnless someone accidentally adds the new enum literal to the end of the list, or decided to give non-contiguous values to the literals (e.g. enum {} NONE = 0, START = 4, HEY = 7 etc....).