> How can I make this IMPOSSIBLE (so that ONLY a value from the expected
enumerated type can be fed to the variable, with no implicit
conversion allowed ?).
"Impossible" is a strong word.
However, if you want to "play nice" and restrict yourself to an API
(which has hopefully-obvious paths for release-build optimizations if
desired), do something like I demonstrate below. This can become
considerably easier if you don't allow "holes" in the values you
operate on, and easier yet again if you always start at zero (e.g.
don't provide MY_ENUM_VAL).
The way this is split between headers and implementation files is left
to the reader. The key here is that the list of enum names is only
defined in one list. Duplication being the root of all evil and all
that...
I have used a system much like this for file reading and writing, where
the code that read and wrote enums used the symbolic version of the
enum value, so config files would be more readily readable by the end
user.
#define MY_ENUM_LIST \
MY_ENUM(Apple) \
MY_ENUM(Banana) \
MY_ENUM_VAL(Avocado, 26)
#define MY_ENUM(x) x,
#define MY_ENUM_VAL(x, y) x = y,
typedef enum _Fruit
{
MY_ENUM_LIST
} Fruit;
#undef MY_ENUM
#undef MY_ENUM_VAL
#define MY_ENUM(x) x,
#define MY_ENUM_VAL(x, y) x,
Fruit g_allowedFruit[] = { MY_ENUM_LIST };
int g_numAllowedFruits = sizeof(g_allowedFruit) /
sizeof(g_allowedFruit[0]);
#undef MY_ENUM
#undef MY_ENUM_VAL
int FindFruit(Fruit f)
{
/* Binary search the allowed list, and return the correct index.
Return -1 on error */
}
Fruit NextEnum(Fruit f)
{
int index = FindFruit(f)
index++;
if (index < g_numAllowedFruits)
return g_allowedFruit[index];
else
ItsAnError();
}
Fruit PreviousEnum(Fruit f)
{
int index = FindFruit(f)
index--;
if (index >= 0)
return g_allowedFruit[index];
else
ItsAnError();
}
int ValidateEnum(Fruit f)
{
return (FindFruit(f) >= 0);
}