Поскольку угловые скобки могут также представлять (или происходят в) операторы сравнения <
, >
, <=
и >=
, макро расширение не может игнорировать запятые внутри угловые скобки , как это происходит в круглых скобках. (Это также проблема для квадратных и фигурных скобок, хотя они обычно встречаются как сбалансированные пары.) Вы можете заключить аргумент макроса в круглые скобки:
FOO((std::map<int, int>), map_var);
Проблема в том, что параметр остается заключенным в круглые скобки внутри раскрытия макроса, что предотвращает его чтение как тип в большинстве контекстов.
Хороший прием для обхода этой проблемы состоит в том, что в C ++ вы можете извлечь имя типа из имени типа в скобках, используя тип функции:
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
FOO((std::map<int, int>), map_var);
Поскольку при формировании типов функций лишние скобки игнорируются, вы можете использовать этот макрос со скобками или без них, если имя типа не включает запятую:
FOO((int), int_var);
FOO(int, int_var2);
В C, конечно, в этом нет необходимости, потому что имена типов не могут содержать запятых вне скобок. Итак, для кросс-языкового макроса вы можете написать:
#ifdef __cplusplus__
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
#else
#define FOO(t,name) t name
#endif