Сколько можно сделать с макросами (высшего порядка)? - PullRequest
3 голосов
/ 06 мая 2009

Безопасно ли давать имена макросов в качестве аргументов другим макросам для имитации функций более высокого порядка?

т.е. куда мне смотреть, чтобы не выстрелить себе в ногу?

Вот некоторые фрагменты:

#define foreach_even(ii, instr) for(int ii = 0; ii < 100; ii += 2) { instr; }
#define foreach_odd(ii, instr)  for(int ii = 1; ii < 100; ii += 2) { instr; }

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

Как насчет частичного заявления, я могу это сделать? :

#define foreach(ii, start, end, step, instr) \
  for(int ii = start; ii < end; ii += step) { instr; }

#define foreach_even(ii, instr) foreach(ii, 0, 100, instr)
#define foreach_odd(ii, instr)  foreach(ii, 1, 100, instr)

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

А можно ли определить макрос внутри макроса?

#define apply_first(new_macro, macro, arg) #define new_macro(x) macro(arg,x)

Ответы [ 2 ]

3 голосов
/ 06 мая 2009

Если вы используете максимально возможный препроцессор, вы можете попробовать boost.preprocessor .

Но учтите, что небезопасно . Запятые, например, вызывают множество проблем при использовании препроцессоров. Не забывайте, что препроцессоры не понимают (или даже пытаются понять) какой-либо код, который они генерируют.

Мой основной совет - «не делай этого» или «делай это как можно осторожнее».

1 голос
/ 06 мая 2009

Я реализовал маленькую прогнившую инфраструктуру модульного тестирования полностью в c-препроцессоре. Несколько десятков макросов, множество макросов - это аргумент для другого типа макроса.

Такие вещи не"безопасны" в лучшем смысле этого слова. Есть тонкие и очень мощные способы выстрелить себе в ногу. Проект модульного тестирования - это игрушка, вышедшая из-под контроля.

Не знаю, можете ли вы вложить определения макросов. Я сомневаюсь в этом, но я пойду попробую ... gcc это не нравится, и отвечает

nested_macro.cc: 8: ошибка: отклонение '#' в программе
nested_macro.cc:3: ошибка: ожидаемый конструктор, деструктор или преобразование типов перед '(' токен
nested_macro.cc:3: ошибка: ожидаемое объявление до токена '}'

Самостоятельное подключение : Если вам интересно, структуру модульного тестирования можно найти по адресу https://sourceforge.net/projects/dut/

...