Debido corchetes angulares también pueden representar (o producirse en) los operadores de comparación <
, >
, <=
y >=
, la expansión macro no puede ignorar comas dentro de corchetes angulares como lo hace dentro de paréntesis. (Esto también es un problema para los corchetes y llaves, aunque estos suelen aparecer como pares equilibrados). Puede encerrar el argumento macro entre paréntesis:
FOO((std::map<int, int>), map_var);
El problema es entonces que el parámetro permanece entre paréntesis dentro de la expansión de la macro, lo que evita que se lea como un tipo en la mayoría de los contextos.
Un buen truco para solucionar esto es que en C ++, puede extraer un nombre de tipo de un nombre de tipo entre paréntesis utilizando un tipo de función:
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);
Debido a que la formación de tipos de función ignora los paréntesis adicionales, puede usar esta macro con o sin paréntesis donde el nombre del tipo no incluye una coma:
FOO((int), int_var);
FOO(int, int_var2);
En C, por supuesto, esto no es necesario porque los nombres de tipo no pueden contener comas fuera de paréntesis. Entonces, para una macro en varios idiomas, puede escribir:
#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