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

Можно ли передать инициализатор, заключенный в скобки, в качестве макропараметра?

У меня есть функция, которую я вызываю так:

literal<long[2]>({1, 2});

Я хочу написать макрос, который расширяется до этого утверждения, например:

MYMACRO(long[2], {1, 2})

К сожалению, препроцессор не знает о скобках, поэтому он видит три аргумента (второй и третий - {1 и 2} соответственно).

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

Но в этом случае размещение в скобках вставленного в скобки инициализатора изменит его значение:

literal<long[2]>(({1, 2}));

(g++ 4.8) error: left operand of comma operator has no effect [-Werror=unused-value]

Является ли это ошибкой GCC или исправлена ​​по дизайну? Есть ли способ сделать то, что я хочу?

Update

Вероятно, я должен был быть более ясным в формулировке исходных вопросов. Препроцессор не изменился навсегда (даже переменные макросы долгое время были расширением GCC). Практические обходные пути в этом случае полезны, но они также очень хорошо известны, а не то, что я хочу получить.

Я действительно хочу знать, было ли что-то добавлено в С++ 11 специально для решения этой проблемы (или это был надзор?). Причудливая обработка фигурных скобок в макросочетаниях кажется сейчас гораздо более серьезной проблемой, учитывая значительно расширенное использование списков, заключенных в фигурные скобки на всем языке.

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

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

4b9b3361

Ответ 1

Вы можете использовать __VA_ARGS__:

#define MYMACRO(T,...) literal<T>(__VA_ARGS__);

Если у вас есть больше параметров, вы можете использовать косвенные действия:

#define UNWRAP(...) __VA_ARGS__
#define MYMACRO(T,A) literal<T>(UNWRAP A);

и теперь вы можете использовать

MYMACRO( long[2], ({1, 2}) )

Обновленный ответ

Вы также можете, если хотите, заменить фигурные скобки в вызове макроса круглыми скобками:

#define BRACED_INIT_LIST(...) {__VA_ARGS__}
#define MYMACRO(T,A) literal<T>(BRACED_INIT_LIST A);

и вызовите

MYMACRO( long[2], (1, 2) )

который IMHO соответствует типичным стилям макро-вызова.

Некоторые слова по другим вопросам: препроцессор ничего не знает о языке (C, С++, С++ 11) и, следовательно, не должен заботиться о специальном значении символов. Он отслеживает круглые скобки, но почти все остальное - всего лишь токены.

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

Наконец, это, конечно, не ошибка в GCC, поскольку компилятор просто реализует то, что говорит стандарт.