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
Passing as Const and by Reference - Worth It
Profiling the C++ Compilation Process
C++: Where to Initialize Variables in Constructor
Cmake Unable to Determine Linker Language with C++
How to Convert Cstring and Std::String Std::Wstring to Each Other
How to Use SQLite in a Multi-Threaded Application
Is There Any Reason to Use the 'Auto' Keyword in C++03
How to Connect MySQL Database Using C++
How to Make This C++ Object Non-Copyable
How to Safely Use Openmp with C++11
Should I Pass an Std::Function by Const-Reference
Generating an Interface Without Virtual Functions