Enums are one of those things which break the ODR, unless you program them carefully. There is actually a macro trick (called, unsurprisingly, the “enum macro trick”) which people who know their stuff use.
First, declare your enumerated values using a macro form:
1 2 3 4 5 6 7 8
|
#define TOKEN_TYPES( F ) \
F(ID) \
F(KeyWord) \
F(Operator) \
F(Expression) \
F(String) \
F(Number) \
F(Char)
|
Now you need to instantiate the enum proper, which should be in the same place as your
TOKEN_TYPES macro (the .hpp file):
1 2 3
|
#define F(name) name ,
enum token_types { TOKEN_TYPES( F ) NumTokenTypes };
#undef F
|
You should also declare a couple of functions to transform those enums to or from strings:
1 2
|
std::string token_type_to_string( token_types );
token_types string_to_token_type( const std::string& );
|
In your source (.cpp file) you can now instantiate both the lookup table and the functions to do the look ups for the user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
#define F(name) #name ,
const char* token_type_names[] = { TOKEN_TYPES( F ) nullptr };
#undef F
std::string token_type_to_string( token_types token )
{
return ((int)token < (int)NumTokenTypes)
? token_type_names[ (int)token ]
: "";
}
token_types string_to_token_type( const std::string& s )
{
return std::find( token_type_names, token_type_names + NumTokenTypes, s ) - token_type_names;
// You could raise an exception if the above expression == NumTokenTypes, if you wanted
}
|
Whatever else you provide is up to you (such as << and >> operator overloads).
This is a very simple version of the Enum Macro Trick. You can do all kinds of fun and interesting things with it, such as providing multiple data per enum, instantiating it as a different type (not necessarily an enum, but as any kind of constant value, or a std::map lookup, or whatever).
When using a strictly 0..N valued-enum, the number of items in the enum is easy (as demonstrated above). But you can even provide an F() macro which simply counts the number of elements:
1 2 3
|
#define F(...) + 1
auto NumTokenTypes = TOKEN_TYPES( F );
#undef F
|
Hope this helps.
Disclaimer: I just typed this all off the top of my head. Dumb typos or mistakes could have been made.