Есть ли способ сделать #define внутри другого #define?
Я знаю, что я пытаюсь стрелять в ногу;) Однако это позволит мне сделать остаток (большую сумму) кода более компактным и читаемым.
Есть ли какой-нибудь сложный способ создать макрос препроцессора внутри другого макроса препроцессора?
Вот пример, что я ищу. Мой реальный сценарий более сложный
- Расширение макроскопического расширения MSVC ++
- Как объединить два раза с препроцессором C и развернуть макрос, как в «arg ## _ ## MACRO»?
- Почему macros препроцессора злые и какие альтернативы?
- Как я могу увидеть исходный файл C / C ++ после предварительной обработки в Visual Studio?
- Стандартная альтернатива трюку ## __ VA_ARGS__ GCC?
// 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 }
- Когда macros C ++ полезны?
- Компилировать, создавать или архивировать проблемы с Xcode 4 (и зависимостями)
- C / C ++ макрос / шаблон blackmagic для генерации уникального имени
- Сначала препроцессор C комментирует или расширяет macros?
- Можем ли мы иметь рекурсивные macros?
- Просмотр расширенных макросов C
- Являются ли typedef и #define одинаковыми в c?
- Строка макроопределения
Стандарт C ++ говорит (16.3.4.3):
Полученная полностью макрозаменяемая последовательность токенов предварительной обработки [… расширения макроса …] не обрабатывается как директива предварительной обработки, даже если она похожа на одну …
Так нет, нет «официального» способа достижения того, что вы хотите с помощью макросов.
Нет. Даже если макрос расширяется во что-то, что выглядит как предпроцессорная директива, расширение не оценивается как директива предварительной обработки.
В дополнение к ответам выше, если вы действительно хотели предварительно обработать исходный файл дважды, что почти наверняка не то, что вы на самом деле хотите сделать, вы всегда можете вызвать свой компилятор следующим образом:
g++ -E input.cpp | g++ -c -x c++ - -o output.o
То есть, запустите файл через препроцессор, затем запустите предварительно обработанный вывод через канал через полную процедуру компиляции, включая второй шаг предварительной обработки. Для того, чтобы это имело достаточно хорошие шансы на работу, я бы предположил, что вам нужно быть достаточно осторожным в том, как вы определили и использовали свои macros, и все это, скорее всего, не стоило бы того, время.
Если вы действительно хотите использовать macros, используйте стандартные макро-решения. Если вам действительно нужно метапрограммирование времени компиляции, используйте шаблоны.
Что касается немного примечания, это напоминает мне о том, что raytracing language POV-Ray сильно использовал довольно сложный язык предварительной обработки с директивами управления streamом, такими как #while
которые допускали условное повторение, вычисления времени компиляции и другие подобные лакомства. Это было бы так на C ++, но это просто не так, поэтому мы просто делаем это по-другому.
Нет. Препроцессор является однопроходным. Он не переоценивает расширения макросов.
Что бы вы купили, во всяком случае? Вы можете выполнить то же самое, что и ваш пример, просто «вложив» второй макрос в первый. например:
#define MACRO(B) B+B void foo() { int a = MACRO(5); }
Как уже отмечалось, можно # включить конкретный файл более одного раза с активными различными определениями макросов. Это может сделать его практичным для достижения некоторых эффектов, которые не могут быть практически достигнуты с помощью каких-либо других средств.
В качестве простого примера, во многих встроенных системах указатель-указатель очень дорог по сравнению с прямым доступом к переменной. Код, который использует много указателей, может быть в два раза больше и медленнее, чем код, который просто использует переменные. Следовательно, если конкретная подпрограмма используется с двумя наборами переменных, в сценарии, в котором обычно можно было бы передать указатель на структуру, а затем использовать оператор стрелки, может быть намного эффективнее простого поставить подпрограмму в свой собственный файл (Обычно я использую расширение .i), которое # включается один раз без макроса _PASS2, и во второй раз. Этот файл может затем #ifdef _PASS2 / # else определять macros для всех переменных, которые должны быть разными в течение двух проходов. Даже при том, что код генерируется дважды, на некоторых микронах, которые занимают меньше места, чем при использовании оператора стрелки с переданными указателями.
Взгляните на m4. Он похож на cpp, но рекурсивный и гораздо более мощный. Я использовал m4 для создания структурированного языка для ассемблеров, например
cmp r0, #0 if(eq) mov r1, #0 else add r1, #1 end
«If», «else» и «end» – это вызовы макросов m4, которые я написал, которые генерируют прыжки и метки, а остальная – assembly. Чтобы вложить эти конструкторы if / else / end, вам нужно определить внутри макроса.