patterncMinor
Suggesting "safe enum" class for ISO C
Viewed 0 times
enumsuggestingforsafeisoclass
Problem
There are quite some questions and answers about how to make
My solution adds the overhead of a pointer dereference for getting the actual enum value, but I think this is a fair deal for situations where you would otherwise have to check for the valid range in a lot of places. Comparing values works naturally with the
I'm posting it here for review and comments if you like -- please tell me if you spot a bug or any other weakness in my idea. Is there anything I overlooked?
The "implementation" is just a header file:
csafenum.h
```
#ifndef CSAFENUM_H
#define CSAFENUM_H
#ifndef __GNUC__
#define __attribute__(x)
#endif
#include
/ declare an enum type: CSAFENUM_DECL(TypeName); /
#define CSAFENUM_DECL(tname) struct tname##_struct; \
typedef const struct tname##_struct * tname; \
const char *tname##_name(tname e) __attribute__((nonnull(1))); \
int tname##_val(tname e) __attribute__((nonnull(1)))
/ declare an enum member: CSE_DECL(TypeName, MemberName); /
#define CSE_DECL(tname, name) extern const struct tname##_struct * const name
/ define an enum type: CSAFENUM_DEF(TypeName); /
#define CSAFENUM_DEF(tname) struct tname##_struct { \
int val; \
const char * const name; \
}; \
const char *tname##_name(tname tname##_cannot_be_null) \
{ \
assert(tname##_cannot_be_null); \
return tname##_cannot_be_null->name; \
} \
int tname##_val(tname tname##_cannot_be_null) \
{ \
assert(tname##_cannot_be_null); \
return tname##_cannot_be_null->val; \
} \
struct tname##_struct
/ define an enum member: CSE_DEF(TypeName, MemberName, IntegerValue); /
#define CSE_DEF(tname, name, v) \
static const struct tname##_struct name##_m
enum really type-safe and I didn't find a solution that ensures both type safety and valid values. So I took some ideas and extended it to my own generic solution, somehow resembling to enum classes used in some other languages.My solution adds the overhead of a pointer dereference for getting the actual enum value, but I think this is a fair deal for situations where you would otherwise have to check for the valid range in a lot of places. Comparing values works naturally with the
== operator because there is only one global constant instance of each enum value.I'm posting it here for review and comments if you like -- please tell me if you spot a bug or any other weakness in my idea. Is there anything I overlooked?
The "implementation" is just a header file:
csafenum.h
```
#ifndef CSAFENUM_H
#define CSAFENUM_H
#ifndef __GNUC__
#define __attribute__(x)
#endif
#include
/ declare an enum type: CSAFENUM_DECL(TypeName); /
#define CSAFENUM_DECL(tname) struct tname##_struct; \
typedef const struct tname##_struct * tname; \
const char *tname##_name(tname e) __attribute__((nonnull(1))); \
int tname##_val(tname e) __attribute__((nonnull(1)))
/ declare an enum member: CSE_DECL(TypeName, MemberName); /
#define CSE_DECL(tname, name) extern const struct tname##_struct * const name
/ define an enum type: CSAFENUM_DEF(TypeName); /
#define CSAFENUM_DEF(tname) struct tname##_struct { \
int val; \
const char * const name; \
}; \
const char *tname##_name(tname tname##_cannot_be_null) \
{ \
assert(tname##_cannot_be_null); \
return tname##_cannot_be_null->name; \
} \
int tname##_val(tname tname##_cannot_be_null) \
{ \
assert(tname##_cannot_be_null); \
return tname##_cannot_be_null->val; \
} \
struct tname##_struct
/ define an enum member: CSE_DEF(TypeName, MemberName, IntegerValue); /
#define CSE_DEF(tname, name, v) \
static const struct tname##_struct name##_m
Solution
Another problem with making the enum values pointers, is that it changes the in-memory representation of an enum. There are many situations where it's necessary for the enum to be an int (such as reading/writing structs to/from files).
If you need type-checked enums, it is better to use C++.
If you need type-checked enums, it is better to use C++.
Context
StackExchange Code Review Q#96069, answer score: 2
Revisions (0)
No revisions yet.