Я использую шаблон макроса X, чтобы сохранить связку массивов/элементов в синхронизации, и я хочу создать список аргументов, но я не могу найти способ получить хорошо сформированный список. Вот что я имею в виду:
#define MY_DATA \
X(var_one, e_one, 1) \
X(var_two, e_two, 2) \
X(var_three, e_three, 3) \
#define X(a,b,c) b,
enum MyNumbers {
MY_DATA
};
#undef X
#define X(a,b,c) c,
int MyValues[] = {
MY_DATA
};
#undef X
void my_func(int a, int b, int c) {} // example do-nothing proc
void main(void)
{
int var_one = MyValues[e_one];
int var_two = MyValues[e_two];
int var_three = MyValues[e_three];
#define X(a,b,c) a,
my_func(MY_DATA); // this fails because of the trailing comma
#undef X
}
Макросы на самом деле не мои сильные стороны, поэтому я не могу придумать способ избавиться от последней запятой в вызове функции. Может ли кто-нибудь подумать о способе остановить его?
Посмотрите на библиотеку Preostcessor Boost для "препроцессорных метапрограммирующих инструментов, включая повторение и рекурсию".
Даже если вы не используете свой полный пакет, в главе I, в которой я расскажу, описаны некоторые методы, в частности, итерация для построения структур данных и операторов.
Вот идея: напишите
my_func(MY_DATA 0);
и объявите my_func для принятия дополнительного (проигнорированного) аргумента.
void my_func(int a, int b, int c, int)
Я часто использую вариант этого шаблона. Однако он обычно используется для определения сопоставлений между данными. В соответствии с этим:
MESSAGE(10, "Some error message"),
MESSAGE(11, "Som other error message"),
Что не имеет смысла в вашем подходе, так это то, что обычно эти конструкции используются для большого количества записей (100, 1000). Обычно вы не хотите, чтобы многие аргументы функции.
Если вы действительно хотите следовать этому подходу, вы можете добавить еще один MACRO
#define MY_DATA\X (var_one, e_one, 1) COMMA\X (var_two, e_two, 2) COMMA\X (var_three, e_three, 3)\
и определите запятую по мере необходимости, когда вы определяете X. (Или вы можете просто поместить запятую непосредственно).
Вот вариант:
void my_func(int a, int b, int c, int dummy) {}
//...
my_func(MY_DATA 0);
Если вы не можете изменить my_func
тогда сделайте thunk (т.е. промежуточную функцию, которая вызывает my_func)
Второй вариант - включить запятую в макрос MY_DATA
вместо X
:
#define MY_DATA \
X(var_one, e_one, 1), \
X(var_two, e_two, 2), \
X(var_three, e_three, 3)