16
votes

Say you want to generate a matched list of identifiers and strings

enum
{
NAME_ONE,
NAME_TWO,
NAME_THREE
};

myFunction(NAME_ONE, "NAME_ONE");
myFunction(NAME_TWO, "NAME_TWO");
myFunction(NAME_THREE, "NAME_THREE");

..without repeating yourself, and without auto-generating the code, using C/C++ macros

Initial guess:

You could add an #include file containing

myDefine(NAME_ONE)
myDefine(NAME_TWO)
myDefine(NAME_THREE)

Then use it twice like:

#define myDefine(a) a,
enum {
#include "definitions"
}
#undef myDefine

#define myDefine(a) myFunc(a, "a");
#include "definitions"
#undef myDefine

but #define doesn't let you put parameters within a string?

2

2 Answers

26
votes

For your second #define, you need to use the # preprocessor operator, like this:

#define myDefine(a) myFunc(a, #a);

That converts the argument to a string.

3
votes

Here's a good way to declare name-list:

#define FOR_ALL_FUNCTIONS(F)\
  F(NameOne)\
  F(NameTwo)\
  F(NameThree)\

#define DECLARE_FUNCTION(N)\
    void N();

#define IMPLEMENT_FUNCTION(N)\
    void N(){}

FOR_ALL_FUNCTIONS(DECLARE_FUNCTION);
FOR_ALL_FUNCTIONS(IMPLEMENT_FUNCTION);

This way this name-list can be re-used multiple times. I have used it for prototyping new language features, although never ended up using them. So, if nothing else, they were a great way to find dead-ends in own inventions. I wonder if it's because what they say: "macros are bad"... :)