Существует ли способ сделать #define в другом #define?

Я знаю, что пытаюсь застрелиться в участке ;) Однако это позволит мне делать остальных (большая сумма) кода меньший и более читаемый.

Там какой-либо хитрый путь состоит в том, чтобы создать макрос препроцессора в другом макросе препроцессора?

Вот пример, что я ищу. Мой реальный сценарий более сложен

// That's what I want to do and surely C++ doesn't like it.
#define MACROCREATER(B) #define MACRO##B B+B

void foo()
{
 MACROCREATOR(5) // This should create new macro (#define MACRO5 5+5)

 int a = MACRO5; // this will use new macro
}
47
задан a3f 16 April 2015 в 08:19
поделиться

6 ответов

Нет. Даже если макрос расширяется во что-то похожее на директиву предварительной обработки, расширение не оценивается как директива предварительной обработки.

15
ответ дан 26 November 2019 в 19:41
поделиться

No. Препроцессор однопроходный. Он не переоценивает расширения макросов.

7
ответ дан 26 November 2019 в 19:41
поделиться

Как уже отмечалось, можно # включить один конкретный файл более одного раза с различными активными определениями макросов. Это может сделать практичным достижение некоторых эффектов, которые практически невозможно достичь никакими другими средствами.

В качестве простого примера: во многих встроенных системах косвенный указатель обходится очень дорого по сравнению с прямым доступом к переменной. Код, который использует много косвенных указателей, вполне может быть в два раза больше и медленнее, чем код, который просто использует переменные.Следовательно, если конкретная процедура используется с двумя наборами переменных, в сценарии, где обычно передается указатель на структуру, а затем используется оператор стрелки, может быть гораздо эффективнее просто поместить подпрограмму в ее собственный файл. (Обычно я использую расширение .i), которое #included один раз без определения макроса _PASS2, а второй раз с. Затем этот файл может #ifdef _PASS2 / # else определить макросы для всех переменных, которые должны быть разными на двух проходах. Несмотря на то, что код генерируется дважды, на некоторых микросхемах он занимает меньше места, чем использование оператора стрелки с переданными указателями.

3
ответ дан 26 November 2019 в 19:41
поделиться

Стандарт C ++ говорит (16.3.4.3):

Результат полностью токен предварительной обработки с заменой макроса последовательность [... раскрытия макроса ...] не обрабатывается как директива предварительной обработки, даже если она похож на один ...

Так что нет, не существует «официального» способа добиться желаемого с помощью макросов.

47
ответ дан 26 November 2019 в 19:41
поделиться

Взгляните на m4. Он похож на cpp, но рекурсивен и намного более мощный. Я использовал m4 для создания структурированного языка для ассемблеров, например

  cmp r0, #0
  if(eq)
    mov r1, #0
  else
    add r1, #1
  end

«if», «else» и «end» - это вызовы макросов m4, которые я написал, которые генерируют переходы и метки, остальное - это собственная сборка. Чтобы вложить эти конструкции if / else / end, вам нужно сделать определения внутри макроса.

3
ответ дан 26 November 2019 в 19:41
поделиться

В дополнение к приведенным выше ответам, если вы действительно хотели предварительно обработать исходный файл дважды, что почти наверняка не то, что вы на самом деле хотите сделать - вы всегда можете вызвать свой компилятор следующим образом:

g++ -E input.cpp | g++ -c -x c++ - -o output.o

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

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

Кстати, это напоминает мне о том, что язык трассировки лучей POV-Ray широко использовал довольно сложный язык предварительной обработки с такими директивами управления потоком, как # while , которые допускали условное повторение. , вычисления во время компиляции и другие подобные полезности. Если бы это было так в C ++, но это просто не так, поэтому мы просто делаем это по-другому.

9
ответ дан 26 November 2019 в 19:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: