Подтвердить что ты не робот

Есть ли способ сделать #define внутри другого #define?

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

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

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

// That 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
}
4b9b3361

Ответ 1

В стандарте С++ говорится (16.3.4.3):

Полученный результат полностью маркеры с предварительной заменой макросов последовательность [... расширения макроса...] не обрабатывается как препроцессора, даже если это напоминает один...

Нет, нет "официального" способа достижения того, что вы хотите с помощью макросов.

Ответ 2

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

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