Я знаю, что пытаюсь застрелиться в участке ;) Однако это позволит мне делать остальных (большая сумма) кода меньший и более читаемый.
Там какой-либо хитрый путь состоит в том, чтобы создать макрос препроцессора в другом макросе препроцессора?
Вот пример, что я ищу. Мой реальный сценарий более сложен
// 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
}
Нет. Даже если макрос расширяется во что-то похожее на директиву предварительной обработки, расширение не оценивается как директива предварительной обработки.
No. Препроцессор однопроходный. Он не переоценивает расширения макросов.
Как уже отмечалось, можно # включить один конкретный файл более одного раза с различными активными определениями макросов. Это может сделать практичным достижение некоторых эффектов, которые практически невозможно достичь никакими другими средствами.
В качестве простого примера: во многих встроенных системах косвенный указатель обходится очень дорого по сравнению с прямым доступом к переменной. Код, который использует много косвенных указателей, вполне может быть в два раза больше и медленнее, чем код, который просто использует переменные.Следовательно, если конкретная процедура используется с двумя наборами переменных, в сценарии, где обычно передается указатель на структуру, а затем используется оператор стрелки, может быть гораздо эффективнее просто поместить подпрограмму в ее собственный файл. (Обычно я использую расширение .i), которое #included один раз без определения макроса _PASS2, а второй раз с. Затем этот файл может #ifdef _PASS2 / # else определить макросы для всех переменных, которые должны быть разными на двух проходах. Несмотря на то, что код генерируется дважды, на некоторых микросхемах он занимает меньше места, чем использование оператора стрелки с переданными указателями.
Стандарт C ++ говорит (16.3.4.3):
Результат полностью токен предварительной обработки с заменой макроса последовательность [... раскрытия макроса ...] не обрабатывается как директива предварительной обработки, даже если она похож на один ...
Так что нет, не существует «официального» способа добиться желаемого с помощью макросов.
Взгляните на m4. Он похож на cpp, но рекурсивен и намного более мощный. Я использовал m4 для создания структурированного языка для ассемблеров, например
cmp r0, #0
if(eq)
mov r1, #0
else
add r1, #1
end
«if», «else» и «end» - это вызовы макросов m4, которые я написал, которые генерируют переходы и метки, остальное - это собственная сборка. Чтобы вложить эти конструкции if / else / end, вам нужно сделать определения внутри макроса.
В дополнение к приведенным выше ответам, если вы действительно хотели предварительно обработать исходный файл дважды, что почти наверняка не то, что вы на самом деле хотите сделать - вы всегда можете вызвать свой компилятор следующим образом:
g++ -E input.cpp | g++ -c -x c++ - -o output.o
То есть запустить файл через препроцессор, а затем запустить предварительно обработанный вывод через конвейер через полную процедуру компиляции, включая второй этап предварительной обработки. Я полагаю, что для того, чтобы у этого были достаточно хорошие шансы на работу, вам нужно быть довольно осторожным в том, как вы определяете и используете свои макросы, и в целом, скорее всего, это не будет стоить проблем и увеличения сборки время.
Если вам действительно нужны макросы, используйте стандартные решения на основе макросов. Если вам действительно нужно метапрограммирование во время компиляции, используйте шаблоны.
Кстати, это напоминает мне о том, что язык трассировки лучей POV-Ray широко использовал довольно сложный язык предварительной обработки с такими директивами управления потоком, как # while
, которые допускали условное повторение. , вычисления во время компиляции и другие подобные полезности. Если бы это было так в C ++, но это просто не так, поэтому мы просто делаем это по-другому.