Как я могу использовать круглые скобки в параметрах макроса С++?

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

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

#define MACRO_TEST_1( X , Y ) X && Y

MACRO_TEST_1 ( A , B )
// Desired result: A && B
// Actual result:  A && B

MACRO_TEST_1 ( ( C , D ) )
// Desired result: ( C && D )
// Actual result:  ( C , D ) &&
// Warning: "not enough actual parameters for macro 'MACRO_TEST_1'"

Похоже, что добавление открывающей скобки к первому параметру и закрывающей скобки ко второму параметру заставляет препроцессор рассматривать запятую как часть первого параметра, и поэтому предполагается, что я не предоставил второй параметр вообще.
Об этом свидетельствует предупреждение, а также вывод препроцессора, который ничего не показывает после &&.

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

Я пытался экранировать круглые скобки или запятую, но это не имело значения.
(Тот же результат, только со вставленным escape-символом в вывод препроцессора.)


person Giffyguy    schedule 14.10.2016    source источник
comment
Вам действительно нужно делать это с помощью макросов? Почему?   -  person Frank Puffer    schedule 14.10.2016
comment
@FrankPuffer Я не буду вдаваться в подробности. Странная ситуация, работа со старым кодом - наверное временная. Я полагаю, что, вероятно, есть менее известный трюк, который мне придется использовать, чтобы вставить туда скобки, и это то, что мне нужно на данный момент.   -  person Giffyguy    schedule 14.10.2016
comment
@FrankPuffer Разве у функций не будет такой же проблемы? func(1, 2) — это 2 аргумента, func((1, 2)) — только один аргумент.   -  person Barmar    schedule 14.10.2016
comment
Я не понимаю, почему вы ставите лишние скобки в вызове. Весь смысл скобок в том, чтобы сгруппировать вещи вместе. Когда вы заключаете аргумент функции или макроса в круглые скобки, он становится одним аргументом.   -  person Barmar    schedule 14.10.2016
comment
@ Бармар, я понимаю. Я думаю, что, поскольку это препроцессор, о котором мы говорим, обычно не существуют обходные пути для таких правил? Я не знал, чтобы препроцессор налагал ограничения, делающие определенные результаты невозможными в прошлом... мне просто кажется странным, что это было бы невозможно.   -  person Giffyguy    schedule 14.10.2016
comment
Препроцессор очень прост, он не предоставляет никакого механизма для манипулирования аргументами на уровне символов. он просто обеспечивает простые замены. Нет возможности убрать лишние скобки.   -  person Barmar    schedule 14.10.2016


Ответы (2)


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

Я думаю, что никак, по крайней мере, в такой реализации макроса.

Из gcc.gnu.org:

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

Начальные и конечные пробелы в каждом аргументе удаляются, а все пробелы между токенами аргумента сводятся к одному пробелу. Скобки внутри каждого аргумента должны быть сбалансированы; запятая в таких скобках не завершает аргумент.

Вы не можете полностью исключить аргументы; если макрос принимает два аргумента, на верхнем уровне его списка аргументов должна стоять ровно одна запятая.

person Edgar Rokjān    schedule 14.10.2016
comment
Спасибо. Это похоже на ситуацию, когда escape-символ ДОЛЖЕН разумно иметь возможность изменить значение символов скобок. Жаль, что это не так - макросы могли бы быть более широкими/гибкими, если бы можно было избежать круглых скобок. - person Giffyguy; 14.10.2016
comment
@Giffyguy В любом случае макросы - это просто наследие C, которое не может быть достаточно гибким для многих целей, так что ... у нас есть то, что есть :) - person Edgar Rokjān; 14.10.2016

Технически я нашел решение, хотя и уродливое.
Вам нужно определить символы для символов скобок.

#define OP (
#define CP )

#define MACRO_TEST_1( X , Y ) X && Y

MACRO_TEST_1 ( A , B )
// Desired result: A && B
// Actual result:  A && B

MACRO_TEST_1 ( OP C , D CP )
// Desired result: ( C && D )
// Actual result:  ( C && D )
person Giffyguy    schedule 15.10.2016