Namespaces for Enum Types - Best Practices

namespaces for enum types - best practices

Original C++03 answer:

The benefit from a namespace (over a class) is that you can use using declarations when you want.

The problem with using a namespace is that namespaces can be expanded elsewhere in the code. In a large project, you would not be guaranteed that two distinct enums don't both think they are called eFeelings

For simpler-looking code, I use a struct, as you presumably want the contents to be public.

If you're doing any of these practices, you are ahead of the curve and probably don't need to scrutinize this further.

Newer, C++11 advice:

If you are using C++11 or later, enum class will implicitly scope the enum values within the enum's name.

With enum class you will lose implicit conversions and comparisons to integer types, but in practice that may help you discover ambiguous or buggy code.

Namespace level enums in c++

With C++11

This answer was originally written in 2011. Now that C++11 support is widely available, the preferred way is to use enum class, as Matthew D. Scholefield points out below:

enum class Player {
User,
Computer
};

The enumerated constants must be qualified with the name of the enum when referenced (e.g., Player::Computer).

Before C++11

No, there's nothing inherently wrong with an enum being public. Bear in mind, however, that enumerated constants cannot be qualified with the name of the enclosing enum type. That is, you cannot write Player::USER or similar to refer to the USER constant; they appear directly in the enclosing namespace. As such, it might be a good idea to set a prefix for your constants so that no name collisions occur.

For instance, consider the following declaration:

enum Player {
PL_USER,
PL_COMPUTER
}

This is safer, because name collisions are much less likely with the "PL_" prefix. Additionally, it improves code readability by hinting at which enum a given constant belongs to.

Languages like C# and Java have adopted a slightly different approach to enums, where one has to specify both the name of the enumeration and the name of the constant, such as Player.USER. A similar effect can be achieved in C++ by embedding the enum declaration within a namespace of its own. For example:

namespace Player {
enum Type {
USER,
COMPUTER
}
}

This has the effect of embedding PLAYER and COMPUTER in the Player namespace instead of the global (or otherwise enclosing) namespace. Whether this is a good approach or not is, in my opinion, a matter of preference.

enum in a namespace

I personally don't like the second variation because the status_ part seems redundant to me. The former version avoids that problem, but having a type status::status looks strange too. Furthermore, a namespace is open to modification, so in case somebody did something like

namespace status {
void error( const char *msg );
}

You would get a compiler error since the function error clashes with your enum value.

I prefer to use a third variation:

struct MouseButton {
enum Value {
Left, Middle, Right
};
};

This lets me write functions like

void handleMouseButton( MouseButton::Value b ) {
switch ( b ) {
case MouseButton::Left: // ...
case MouseButton::Middle: // ...
case MouseButton::Right: // ...
}
}

Equivalent of using namespace X for scoped enumerations?

So, is there a way to avoid having to type CatState:: all the time?

Not before C++20. Just as there's no equivalent for having to type ClassName:: for static class members. You can't say using typename ClassName and then get at the internals. The same goes for strongly typed enums.

C++20 adds the using enum X syntax, which does what it looks like.

You can of course not use enum class syntax, just using regular enums. But then you lose strong typing.

It should be noted that one of the reasons for using ALL_CAPS for weakly typed enums was to avoid name conflicts. Once we have full scoping and strong typing, the name of an enum is uniquely identified and cannot conflict with other names. Being able to bring those names into namespace scope would reintroduce this problem. So you would likely want to use ALL_CAPS again to help disambiguate the names.

Where is the best place to locate enum types?

Why treat enums differently to other types? Keep them in the same namespace as they're likely to be used - and assuming they're going to be used by other classes, make them top-level types in their own files.

The only type of type which I do commonly clump together is delegates - I sometimes have a Delegates.cs file with a bunch of delegates in. Less so with .NET 3.5 and Func/Action, mind you.

What's the best practice to code shared enums between classes

The best practice is creating separate file for each class, enum, or other type.

MyEnum.cs

namespace Foo
{
public enum MyEnum
{
High,
Low
}
}

Class1.cs

namespace Foo
{
public class Class1
{
public MyEnum MyProperty { get; set; }
}
}

Why is enum class preferred over plain enum?

C++ has two kinds of enum:

  1. enum classes
  2. Plain enums

Here are a couple of examples on how to declare them:

 enum class Color { red, green, blue }; // enum class
enum Animal { dog, cat, bird, human }; // plain enum

What is the difference between the two?

  • enum classes - enumerator names are local to the enum and their values do not implicitly convert to other types (like another enum or int)

  • Plain enums - where enumerator names are in the same scope as the enum and their
    values implicitly convert to integers and other types

Example:

enum Color { red, green, blue };                    // plain enum 
enum Card { red_card, green_card, yellow_card }; // another plain enum
enum class Animal { dog, deer, cat, bird, human }; // enum class
enum class Mammal { kangaroo, deer, human }; // another enum class

void fun() {

// examples of bad use of plain enums:
Color color = Color::red;
Card card = Card::green_card;

int num = color; // no problem

if (color == Card::red_card) // no problem (bad)
cout << "bad" << endl;

if (card == Color::green) // no problem (bad)
cout << "bad" << endl;

// examples of good use of enum classes (safe)
Animal a = Animal::deer;
Mammal m = Mammal::deer;

int num2 = a; // error
if (m == a) // error (good)
cout << "bad" << endl;

if (a == Mammal::deer) // error (good)
cout << "bad" << endl;

}

Conclusion:

enum classes should be preferred because they cause fewer surprises that could potentially lead to bugs.

Enum in structure

Since C++11 you can use enum class instead of enum to solve this problem.

If you can't use C++11 for some reason you should prefix your values like this:

enum IN
{
IN_SYSTEMMONITOR,
IN_MODEMANAGEMENT
};

enum OUT
{
OUT_SLIDECONTROL,
OUT_MODEMANAGEMENT,
OUT_HMICONTROL,
OUT_MOTORCONTROL
};

or they can't be placed at the same structure, so you have to move the declarations to different namespaces. (EDIT: or different class / structure as it said below.)

Where should we put our enums?

The best descision depends on how the enumeration is used.

E.g.

  • if the enumeration is only used in one class, you can make it an inner class to that class
  • if the enumeration is used by one class (e.g. A) more than others (e.g. the others call methods on A that have parameters of type of the enumeration; you might want to put it in the same package/namespace as A is in.

In general, find the best package/namespace based on where its used most



Related Topics



Leave a reply



Submit