Удаление последней запятой в макросе

0

Я использую шаблон макроса 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
}

Макросы на самом деле не мои сильные стороны, поэтому я не могу придумать способ избавиться от последней запятой в вызове функции. Может ли кто-нибудь подумать о способе остановить его?

  • 2
    Единственное, о чем я могу думать, это: прекратить (ab) использование макросов.
  • 0
    Это шаблон ? Где это описано?
Показать ещё 2 комментария
Теги:
templates

3 ответа

2

Посмотрите на библиотеку Preostcessor Boost для "препроцессорных метапрограммирующих инструментов, включая повторение и рекурсию".

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

Вот идея: напишите

my_func(MY_DATA 0);

и объявите my_func для принятия дополнительного (проигнорированного) аргумента.

void my_func(int a, int b, int c, int)
  • 0
    Это больше похоже на комментарий.
  • 0
    Да, подход с дополнительными аргументами работает, но я играл с этим подходом, и у него есть два досадных недостатка: 1: вызов выглядит странным, и сопровождающий, вероятно, собирается бросить запятую и целую вечность удивляться, почему он не работает, и 2: мне нужно изменить или подменить все вызовы функций. Я думаю, что я собираюсь вернуться к чертежной доске на этом.
1

Я часто использую вариант этого шаблона. Однако он обычно используется для определения сопоставлений между данными. В соответствии с этим:

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. (Или вы можете просто поместить запятую непосредственно).

  • 0
    Это будет работать, но постепенно становится все более и более сложным. Я думаю, что мне может понадобиться переоценить, как я это делаю.
  • 0
    Если бы вы могли определить массив структур, вы могли бы передать это (указатель) функции, а не каждому элементу в отдельности.
Показать ещё 2 комментария
0

Вот вариант:

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)
  • 0
    Благодарю. Я играл с этим подходом, и у него есть два досадных недостатка: 1: вызов выглядит странно, и сопровождающий, вероятно, собирается бросить запятую и целую вечность задаваться вопросом, почему он не работает, и 2: мне нужно изменить или подложить шим все вызовы функций. Я думаю, что я собираюсь вернуться к чертежной доске на этом.
  • 0
    Вам не нужно изменять все вызовы функций, просто используйте промежуточную функцию.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню