Reputation: 5809
I've got a list of tokens from which I'd like to create an enum (trivial) and an array of strings (to be later used to create a map of string to enum). Here's my attempt:
#define TOKEN_LIST CUBE , SPHERE , CIRCLE
#define CREATE_ARRAY_OF_STRINGS( ... ) const char* token[] = { __VA_ARGS__ };
CREATE_ARRAY_OF_STRINGS( TOKEN_LIST )
// enum SHAPE_TYPE{ TOKEN_LIST }; // easy
int main(int argc, char *argv[])
{
return 1;
}
The problem is that the TOKEN_LIST
is not stringified as shown when I compile with the -E
flag as follows:
const char* token[] = { CUBE , SPHERE , CIRCLE };
int main(int argc, char *argv[])
{
return 1;
}
Where const char* token[] = { CUBE , SPHERE , CIRCLE };
should be const char* token[] = { "CUBE" , "SPHERE" , "CIRCLE" };
Is there any other way to achieve this with C++03? Boost Processor perhaps?
Upvotes: 2
Views: 1209
Reputation: 171127
If you're willing to change the format of your TOKEN_LIST
somewhat, you can easily do this with Boost.Preprocessor.
Here's an example of using a Boost.Preprocessor sequence instead of a comma-separated list:
#define GENERATE_STRING(maZ, maIdx, maTokens) \
BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(maIdx, maTokens))
#define GENERATE_STRINGS(maTokens) \
BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(maTokens), GENERATE_STRING, maTokens)
#define TOKEN_LIST (CUBE)(SPHERE)(CIRCLE)
const char* token[] = { GENERATE_STRINGS(TOKEN_LIST) }
enum ShapeType {
BOOST_PP_SEQ_ENUM(TOKEN_LIST)
};
Since you seem to have access to ...
and __VA_ARGS__
(which are not a C++03 feature), you should be able to use a Boost.Preprocessor tuple as well (comma-delimited list enclosed in parentheses); with support for variadic macros, Boost.Preprocessor is capable of determining tuple size implicitly. However, I have no experience with that, so I cannot provide a code example.
The maZ
argument is an implementation feature of Boost.Preprocessor repetition macros. There are three: z (used by enum-style functions), d (used by while-style functions), and r (used by for-style functions). It is only useful when nesting these contructs, as it allows faster preprocessing. If GENERATE_STRING
was itself calling an enum function, then using BOOST_PP_ENUM_ ## maZ
would be easier on the preprocessor than just using BOOST_PP_ENUM
for the nested invocation (but the latter works as well, as long as you don't exceed the compiler's preprocessing limits).
Upvotes: 2