By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,434 Members | 1,878 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,434 IT Pros & Developers. It's quick & easy.

how to restrict enum conversions ?

P: n/a

Hi all,

A variable with an enumerated type can be set with a value from any
other generic "enum" type in the program, or with an integer value,
without notice to the user, neither at compilation nor at execution.

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 ?).

Is "typedef enum" the way to go ?
Thanks for your insights - oz
Nov 15 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a


O. Zimmermann wrote On 11/15/05 10:58,:
Hi all,

A variable with an enumerated type can be set with a value from any
other generic "enum" type in the program, or with an integer value,
without notice to the user, neither at compilation nor at execution.

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 ?).

Is "typedef enum" the way to go ?


No; an `enum xxx' type is just an ordinary integer
of a compiler-determined flavor, and the enumerated
names themselves are merely `int' constants.

Here's a hack inspired by Java that would solve
part of your problem:

typedef struct {
int value;
} Veggie;

const Veggie AVOCADO = { 1 };
const Veggie BANANA = { 2 };
...
const Veggie ZUCCHINI = { 26 };

typedef struct {
int value;
} Animal;

const Animal AARDVARK = { 1 };
const Animal BEAR = { 2 };
...
const Animal ZEBRA = { 26 };

This will allow `Veggie v1 = AVOCADO', for example,
but `Veggie v2 = AARDVARK' will provoke a compile-time
diagnostic.

It's not perfect, though. You can't prevent someone
from writing `Veggie v3 = { -42 }', for example. Also,
you give up the ability to use AVOCADO et al. as case
labels, or to compare `v3 == ZUCCHINI'. It's up to you
to decide whether the drawbacks of the scheme are more
or less painful than trying to police the use of enums.

--
Er*********@sun.com

Nov 15 '05 #2

P: n/a
"O. Zimmermann" <oz*****@lpsc.in2p3.fr> writes:
A variable with an enumerated type can be set with a value from any
other generic "enum" type in the program, or with an integer value,
without notice to the user, neither at compilation nor at execution.

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 ?).

Is "typedef enum" the way to go ?


Basically, you can't (other than by using a different language).
Enumeration types are really nothing more than thinly veiled integers.
Typedef won't help; it just creates an alias for an existing type, not
a new type.

There are ways to do similar things (Eric Sosman posted some ideas),
but they have drawbacks.

C generally has weak type checking -- or, more precisely, it provides
implicit conversions in a lot of cases. As Eric points out, there are
no such implicit conversions for struct types.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #3

P: n/a
O. Zimmermann wrote:
A variable with an enumerated type can be set with a value from any
other generic "enum" type in the program, or with an integer value,
without notice to the user, neither at compilation nor at execution.

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 ?).


I don't think you can. Switch to a language which focus on safety.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Nov 15 '05 #4

P: n/a
> 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);
}

Nov 15 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.