I have never seen this inside a class and would recommend that you never do this if you want to understand the code the other day.
However, there is a case where I consider this technique acceptable, and it is then that you have a large table from which you need to create several constructions, such as an enumeration and an attribute table. Suppose there are two files:
foobars.h:
enum Foobars { #define FOOBAR(id, description, args) FOOBAR_##id, #include "foobars.tab" #undef FOOBAR }; extern const char *foobar_names[]; const char *parse_foobar(Foobars fb, const char *input);
foobars.cpp:
#include "foobars.h" const char *foobar_names[] = { #define FOOBAR(id, description, args) description, #include "foobars.tab" #undef FOOBAR }; const char *parse_foobar(Foobars fb, const char *input) { switch(fb) { #define INT get_int(&input) #define FLOAT get_float(&input) #define STRING get_string(&input) #define FOOBAR(id, description, args) args #include "foobars.tab" #undef FOOBAR } return input;
And the magic in "foobars.tab" (it is special, so I recommend not to call it Nothing.h or anything.hpp or any other common suffix):
FOOBAR(NULL, "Empty command, does nothing", {})
Another option is to define a macro for the contents of a special include. If the table is short, the macro is easier to read, but if the file is long, a special file makes sense.
The last option is to make the table as a whole different from the format and generate code, but this is due to writing a special script to create it, and this is not so.