Вы можете игнорировать скобки до тех пор, пока вы готовы принять два дополнения:
- весь код должен быть обернут в блок макро
- там должно быть что-то после эхо директивы
eg Таким образом:
#define LPAREN (
#define echo ECHO_MACRO LPAREN
#define done)
#define ECHO_MACRO(X) std::cout << (X) << "\n"
#define DSL(X) X
...
DSL(
echo "Look ma, no brains!" done;
)
...
Причины этого:
- Там нет никакого способа сделать функцию, как макрос расширения без скобок. Это всего лишь базовое требование макроязыка; если вы хотите что-то еще изучить другой макропроцессор
- Поэтому нам нужно вставить круглые скобки; в свою очередь, мы должны иметь что-то после директивы, как в
done
макро, который будет расширяться в форме containinf необходимых близких Paren
- К сожалению, поскольку
echo ... done
форма не выглядит как вызов макроса для препроцессора, он не был отмечен для расширения, когда препроцессор вошел в него, и вставили ли мы парны или нет, это не имеет значения.Поэтому использование echo ... done
приведет к выходу вызова ECHO_MACRO в текст
- Текст повторно сканируется, помечен для расширения и снова разворачивается, когда он является аргументом функционально-подобного макроса, поэтому обертывание всего блока блочным макросом (здесь это
DSL
) заставят вызов ECHO_MACRO быть расширен на этом ReScan прохода (DSL
ничего не делает с результатом: она существует только, чтобы заставить пересканирование)
- Нам нужно, чтобы скрыть
(
в расширении echo
за простым макросом LPAREN
, поскольку в противном случае несогласованная скобка в макрообъекте путает препроцессор
Если вы хотите создать целый предметно-ориентированный язык для таких команд, можно также уменьшить количество done
команд, делая ядро команды еще более громоздким:
#define LPAREN (
#define begin NO_OP LPAREN 0
#define done);
#define echo); ECHO_MACRO LPAREN
#define write); WRITE_MACRO LPAREN
#define add); ADD_MACRO LPAREN
#define sub); SUB_MACRO LPAREN
#define NO_OP(X)
#define ECHO_MACRO(X) std::cout << (X) << "\n"
#define WRITE_MACRO(X) std::cout << (X)
#define ADD_MACRO(D, L, R) (D) = (L) + (R)
#define SUB_MACRO(D, L, R) (D) = (L) - (R)
#define DSL(X) DSL_2 X
#define DSL_2(X) X
int main(void) {
int a, b;
DSL((
begin
add a, 42, 47
sub b, 64, 50
write "a is: "
echo a
write "b is: "
echo b
done
))
return 0;
}
В этой форме каждая команда заранее - предназначен для закрытия предыдущей команды, так что только последний нужен done
; вам нужна линия begin
, так что есть команда открытия первой реальной операции для закрытия, иначе параны будут несоответствовать.
Беспощадно, так как это намного проще в C, чем на C++, поскольку препроцессор C более мощный (он поддерживает __VA_ARGS__
, которые очень важны для сложного макропрограммирования макросов).
Ах да, и еще одна вещь -
... пожалуйста никогда не сделать это в реальном коде.
Что вы хотите объявить? Могут быть и другие способы. Также 'custommacro (x);' является очевидным способом. – Pubby
Все дело в том, что у них нет этих скобок вокруг 'x'. –
невозможно, на мой взгляд, это очень сложно и тонко. Вы должны использовать() и все кепки, чтобы сделать очевидным то, что действительно происходит. Попытка скрыть вещи или сделать «волшебство» почти всегда усложняет ситуацию. Просто выполните 'CUSTOMMACRO (x)'; –