sharptooth
sharptooth

Reputation: 170489

Is there a reason to use enum to define a single constant in C++ code?

The typical way to define an integer constant to use inside a function is:

const int NumbeOfElements = 10;

the same for using within a class:

class Class {
...
    static const int NumberOfElements = 10;
};

It can then be used as a fixed-size array bound which means it is known at compile time.

Long ago compilers didn't support the latter syntax and that's why enums were used:

enum NumberOfElementsEnum { NumberOfElements = 10; }

Now with almost every widely used compiler supporting both the in-function const int and the in-class static const int syntax is there any reason to use the enum for this purpose?

Upvotes: 22

Views: 11608

Answers (9)

Pavel Minaev
Pavel Minaev

Reputation: 101565

The reason is mainly brevity. First of all, an enum can be anonymous:

 class foo {
    enum { bar = 1 };
 };

This effectively introduces bar as an integral constant. Note that the above is shorter than static const int.

Also, no-one could possibly write &bar if it's an enum member. If you do this:

 class foo {
    static const int bar = 1;
 }

and then the client of your class does this:

 printf("%p", &foo::bar);

then he will get a compile-time linker error that foo::bar is not defined (because, well, as an lvalue, it's not). In practice, with the Standard as it currently stands, anywhere bar is used where an integral constant expression is not required (i.e. where it is merely allowed), it requires an out-of-class definition of foo::bar. The places where such an expression is required are: enum initializers, case labels, array size in types (excepting new[]), and template arguments of integral types. Thus, using bar anywhere else technically requires a definition. See C++ Core Language Active Issue 712 for more info - there are no proposed resolutions as of yet.

In practice, most compilers these days are more lenient about this, and will let you get away with most "common sense" uses of static const int variables without requiring a definition. However, the corner cases may differ, however, so many consider it to be better to just use anonymous enum, for which everything is crystal clear, and there's no ambiguity at all.

Upvotes: 30

Tobias Langner
Tobias Langner

Reputation: 10808

There is a difference between those two. Enums don't have an adress as far as I know. static const ints do though. So if someone takes the adress of the const static int, casts away the const, he can modify the value (although the compiler might ignore the change because he thinks it's const). This is of course pure evil and you should not do it - but the compiler can't prevent it. This can't happen with enums.

And of course - if you (for some reason) need the adress of that const, you need the static const int.

In short - enum is an rvalue while const static int is an lvalue. See http://www.embedded.com/story/OEG20011129S0065 for more details.

Upvotes: 2

jrbjazz
jrbjazz

Reputation: 3150

Use of enum have one advantage. An enum type is a type, so if you define, for example:

enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... };

and you have a function like:

void Function1(EnumType Value)

the compiler checks that you are passing a member of the enum EnumType to the function, so only valid values for parameter Value would be EnumValue1 and EnumValue2. If you use constants and change the function to

void Function1(int Value)

the compiler checks that you are passing an int (any int, a constant, variable or literal) to the function.

Enum types are good for grouping related const-values. For only one const value, I do not see any advantage.

Upvotes: 7

SadSido
SadSido

Reputation: 2551

Well, the portability is a good reason for using enum. It is great, because you don't have to worry whether your compiler supports "static const int S = 10" or not...

Also, as far as I remember, static variable must be defined somewhere, as well as declared, and the enum value must be declared only.

Upvotes: 1

Gorpik
Gorpik

Reputation: 11028

The only reason for using the "enum hack" is that old compilers do not support in-class const definitions, as you say in your question. So, unless you suspect that your code will be ported to an old compiler, you should use const where const is due.

Upvotes: 6

Frerich Raabe
Frerich Raabe

Reputation: 94299

In your case, I'd use a constant as well. However, there are other cases where I might be adding other, related constants. Like this:

const int TextFile = 1; // XXX Maybe add other constants for binary files etc.?

In such cases, I use an enum right away with a single value, like this:

enum FileType {
    TextFile = 1
    // XXX Maybe add other values for binary files etc.?
}

The reason is that the compiler can then issue warnings when I'm using the constant value in switch expressions, as in:

FileType type;
// ...
switch ( type ) {
    case TextFile:
       // ...
}

In case I decide to add another constant value which is related to the existing value (a different type of file, in this example), virtually all compilers will issue a warning since the new value is not handled in the switch statement.

If I had used 'int' and constants instead, the compiler wouldn't have a chance to issue warnings.

Upvotes: 6

sbi
sbi

Reputation: 224049

Defining static constants directly in the class definition is a later addition to C++ and many still stick to the older workaround of using an enum for that. There might even be a few older compilers still in use which don't support static constants directly defined in class definitions.

Upvotes: 10

Paolo Tedesco
Paolo Tedesco

Reputation: 57192

I think that there's no reason to use an enum, and that it's actually better to use a static const int for this purpose, since an enum has its own type (even if implicitly convertible to an integer).

Upvotes: 2

Ami
Ami

Reputation: 1110

bottom line - use const.

more details:

I'm not a c++ expert, but this seems a more general design question.

If it's not a must, and you think there's a very low/non-existent probability that the enum will grow to have more then one value, then use a regular const. even if you are wrong and at some point in the future there will be more values, making an enum the right choice - a simple refactoring and you change you const to enum.

Upvotes: -3

Related Questions