Detect When Multiple Enum Items Map to Same Value

Detect when multiple enum items map to same value

There are a couple ways to check this compile time, but they might not always work for you. Start by inserting a "marker" enum value right before MsgFoo2A.

typedef enum
{
MsgFoo1A = BASE1_VAL,
MsgFoo1B,
MsgFoo1C,
MsgFoo1D,
MsgFoo1E,
MARKER_1_DONT_USE, /* Don't use this value, but leave it here. */
MsgFoo2A = BASE2_VAL,
MsgFoo2B
} FOO;

Now we need a way to ensure that MARKER_1_DONT_USE < BASE2_VAL at compile-time. There are two common techiques.

Negative size arrays

It is an error to declare an array with negative size. This looks a little ugly, but it works.

extern int IGNORE_ENUM_CHECK[MARKER_1_DONT_USE > BASE2_VAL ? -1 : 1];

Almost every compiler ever written will generate an error if MARKER_1_DONT_USE is greater than BASE_2_VAL. GCC spits out:

test.c:16: error: size of array ‘IGNORE_ENUM_CHECK’ is negative

Static assertions

If your compiler supports C11, you can use _Static_assert. Support for C11 is not ubiquitous, but your compiler may support _Static_assert anyway, especially since the corresponding feature in C++ is widely supported.

_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");

GCC spits out the following message:

test.c:16:1: error: static assertion failed: "Enum values overlap."
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
^

C++11 Enum class containing duplicate values

There is currently no way to detect or prevent multiple identical enum values in an enum.

The reflection working group is working on how to add reflection -- the ability for C++ code to introspect C++ code -- to the language. In the long list of stuff that reflection covers, there is a short list being worked on, and in that short list, examining the values of an enumeration at compile time is there.

N4428 contains a proposal for enum reflection. There are some partial implementations out there.

Under N4428, detecting duplicates would be easy. You can get the number of enumeration values, and their value, all at compile time. Simply create a pack of all the enum values in order, and test that they are unique. Then toss the result of that test into a static_assert.

The end result could be:

template<class E>
constexpr bool all_values_unique(); // todo

static_assert( all_values_unique<ConnectionState>(), "Duplicate enum value detected" );

Prior to something like that reflection proposal being added to C++, this is not possible.

You can fake it using macros -- have a macro that both creates your enum and creates reflection traits information about it -- then write all_values_unique that uses the reflection traits information. This has the advantage that if/when the standard and/or your compiler gets the reflection features needed, it may be easy to strip out your macros.

Check at compile time that multiple enums have unique values

One way to do this is to create variables using each error code in the variable name:

#define GENERATE_COUNTER(key, value, name) constexpr int IsErrorcodeUnique ## value = 1;

namespace {

ERRORS1_LIST(GENERATE_COUNTER)
ERRORS2_LIST(GENERATE_COUNTER)

} // namespace


Related Topics



Leave a reply



Submit