Как уменьшить количество аргументов в расширении таблицы xmacro

Я работал с таблицами на основе xmacros, как это:

#define TABLE_MACRO(MAN_TYPE, WOMAN_TYPE) \
   MAN_TYPE(   John, Doe, "Addr1", arg_a, arg_b, arg_c)   \
   WOMAN_TYPE( Jane, Joe, "Addr2", arg_a, arg_b, arg_c)   \
   MAN_TYPE(   Bill, Tom, "Addr3", arg_a, arg_b, arg_c)   \

У меня есть таблицы с гораздо большим количеством аргументов, чем то, что я показываю, однако во многих случаях я расширяю таблицу только на 1 или 2. Я использую их для генерации переменных и перечислений. Например:

#define NAME_LIST(name,last,addr, arg1, arg2, arg3) name,\

enum {
   TABLE_MACRO(NAME_LIST,NAME_LIST)
}Name_List;

Есть ли способ взять TABLE_MACRO и переопределить или изменить порядок его расширения, чтобы иметь расширение только к этому?

TABLE_MACRO_NAMES_ONLY(MAN_TYPE, WOMAN_TYPE) \
   MAN_TYPE(   John, )                       \
   WOMAN_TYPE( Jane, )                       \
   MAN_TYPE(   Bill, )                       \

Моя цель состоит в том, чтобы иметь упрощенные таблицы, которые будут использоваться как:

#define NEW_NAME(name)  New_##name,

TABLE_MACRO_NAMES_ONLY(NEW_NAME, NEW_NAME)

1 ответ

Решение

Надеюсь, ожидание окупилось:
Я придумал два решения. Тот, в котором вы можете сохранить исходную таблицу, как есть, но использование немного более неудобно.

Решение 1

// your original table as is
#define TABLE_MACRO(MAN_TYPE, WOMAN_TYPE) \
   MAN_TYPE(   John, Doe, "Addr1", arg_a, arg_b, arg_c)   \
   WOMAN_TYPE( Jane, Joe, "Addr2", arg_a, arg_b, arg_c)   \
   MAN_TYPE(   Bill, Tom, "Addr3", arg_a, arg_b, arg_c)   \

// create Names only table
#define MTYPE(a,b,c,d,e,f) MAN(a)
#define WTYPE(a,b,c,d,e,f) WOMAN(a)
#define TABLE_NAMES_ONLY \
   TABLE_MACRO(MTYPE,WTYPE)

// usage (here, the defines MUST be named "MAN" and "WOMAN".
// At least they have to align with the definition of MTYPE and WTYPE)
#define MAN(name) man_##name
#define WOMAN(name) woman_##name
TABLE_NAMES_ONLY

Другое решение заключается в расширении исходной таблицы двумя аргументами, но в итоге использование становится проще.

Решение 2

// your extended original table (see extra arguments)
#define TABLE_MACRO(MAN_TYPE, WOMAN_TYPE, m_extra, w_extra) \
   MAN_TYPE(   John, Doe, "Addr1", arg_a, arg_b, arg_c, m_extra, w_extra)   \
   WOMAN_TYPE( Jane, Joe, "Addr2", arg_a, arg_b, arg_c, m_extra, w_extra)   \
   MAN_TYPE(   Bill, Tom, "Addr3", arg_a, arg_b, arg_c, m_extra, w_extra)   \

// create Names only table
#define MTYPE(a,b,c,d,e,f, m_extra, w_extra) m_extra(a)
#define WTYPE(a,b,c,d,e,f, m_extra, w_extra) w_extra(a)
#define TABLE_NAMES_ONLY(male_func, female_func) \
   TABLE_MACRO(MTYPE, WTYPE, male_func, female_func)

// usage (here, the naming of the 2 following defines is arbitrary)
#define MAN(a) man_##a
#define WOMAN(a) woman_##a
TABLE_NAMES_ONLY(MAN, WOMAN)

// different usage:
#define NAME(a) name_##a
TABLE_NAMES_ONLY(NAME, NAME)

Оба решения были протестированы с gcc 5.3.0 с использованием gcc -E yourTestFile.c, Возможно, есть даже лучшие решения, но это те, которые пришли мне в голову.

Другие вопросы по тегам