Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are unscoped enumerations still useful?

Tags:

c++

enums

c++11

I haven't found any wording in the C++11 standard that says unscoped enums are deprecated, but from a pragmatic perspective I'm wondering if they are still useful. A lot of people on my team have gotten in the habit of converting unscoped enums to scoped enums, but it's caused some headache:

class foo
{
public:
    enum MyEnum { One, Two, Three };
};

They convert this to:

class foo
{
public:
    enum class MyEnum { One, Two, Three };
};

Which means when these enumerators are used, instead of foo::One, it looks like foo::MyEnum::One. I've been asking the following best-practices:

  1. If you convert to scoped enum, move it out of classes and into global scope or namespace scope (to improve usability and avoid the latter usage example above).
  2. If you keep the enum unscoped, make sure it's in namespace/class/function/etc scope so that it doesn't conflict with other names.

The main difference between the two points is that for #1 we don't put them in classes, which otherwise adds some verbose indirection.

All of this seems like over complication, and seems like it would be much simpler to just keep enumerations already in classes as unscoped enums. What's the general best-practice approach for deciding between the two?

like image 894
void.pointer Avatar asked Dec 05 '14 16:12

void.pointer


People also ask

What is the use of enumerations?

Enumerations make for clearer and more readable code, particularly when meaningful names are used. The benefits of using enumerations include: Reduces errors caused by transposing or mistyping numbers. Makes it easy to change values in the future.

What is the point of enum class?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it.

What is Unscoped enum?

In an unscoped enum, the scope is the surrounding scope; in a scoped enum, the scope is the enum-list itself. In a scoped enum, the list may be empty, which in effect defines a new integral type. class. By using this keyword in the declaration, you specify the enum is scoped, and an identifier must be provided.


1 Answers

Scoped enumerators cannot implicitly convert to their underlying type. If you need your enum values to implicitly convert to their underlying type, you cannot use a scoped enumerator.

An example of when this is useful is when you are talking to an API out of your control, and your enum values are bit flags. The API (you don't control) that expects an uint32_t or some other integral type as a bit flag.

You can override operator| etc in order to keep everything "in type", or have them generate the underlying type -- but a single element of your enum class cannot implicitly convert to uint32_t.

Another use for unscoped enums I find useful is to replace #define FOO 32 style macros. Instead of textual substitution, I get a token that has the same meaning, and I don't have to rewrite the code base. If there are a tightly grouped set of such values, I can eventually reach the point where I can change the int arguments that are expecting such #define tokens to be passed with enum values, and the parameters are now typed!

This allows gradual migration towards a better code base.

The next step might be to use scoped enums for those values, but the overhead of having to do everything at once can mean that the first step may not be taken. The perfect is the enemy of the good.


On the other hand, if your enums are really just a set of enumerated values, and their value in the underlying type is unimportant, then scoped enums are almost always a better idea than unscoped enums. They prevent accidental conversion to the underlying type: if the value in the underlying type is merely an implementation detail, such conversion can cause bugs.

This is by far the most common use case I find for enums -- a list of distinguished values, whose underlying type and value is merely an implementation detail.

like image 157
Yakk - Adam Nevraumont Avatar answered Oct 20 '22 05:10

Yakk - Adam Nevraumont