This is what my #define macro looks like:
#define CUSTOM_COMPARATOR(table, column, a, b) \
do { \
const struct db_##table *row1 = a; \
const struct db_##table *row2 = b; \
\
/* Insert lot of code here with multiple row->##column usage */ \
return strcmp(row1->##column->name1, row2->##column->name2); \
} while (0)
I have to generate multiple definitions based on different table and column types. These definitions are preprocessed and called in multiple functions:
static int
db_table_sometable_somecolumn_comparator(const void *a, const void *b) {
CUSTOM_COMPARATOR(sometable, somecolumn, a, b);
}
static int
db_table_someothertable_someothercolumn_comparator(const void *a, const void *b) {
CUSTOM_COMPARATOR(someothertable, someothercolumn, a, b);
}
Basically I want to avoid the duplication of code inside CUSTOM_COMPARATOR. When I compile this gcc complains that pasting "->" and "somecolumn" does not give a valid preprocessing token which is understandable since -> breaks the token. It works on db_##table because it produces a single token.
Nonetheless, is there any way I can achieve this? I have like 10s of table/columns with just name change but share the same logic mentioned in CUSTOM_COMPARATOR which is also 50 LoC in real.
>Solution :
Don’t try to paste the column name to make a new token. Remember that whitespace in C is ignored, so you can simply do this:
return strcmp(row1-> column ->name1, row2-> column ->name2);
This is accepted by the preprocessor, and expands to, e.g. with gcc -E:
static int
db_table_sometable_somecolumn_comparator(const void *a, const void *b) {
do { const struct db_sometable *row1 = a; const struct db_sometable *row2 = b; return strcmp(row1-> somecolumn ->name1, row2-> somecolumn ->name2); };
}
static int
db_table_someothertable_someothercolumn_comparator(const void *a, const void *b) {
do { const struct db_someothertable *row1 = a; const struct db_someothertable *row2 = b; return strcmp(row1-> someothercolumn ->name1, row2-> someothercolumn ->name2); };
}
which is perfectly valid C.