Porque colchetes também pode representar (ou ocorrem em) os operadores de comparação <
, >
, <=
e >=
, a expansão macro não pode ignorar vírgulas dentro de colchetes como ele faz entre parênteses. (Isso também é um problema para colchetes e colchetes, embora eles geralmente ocorram como pares equilibrados.) Você pode colocar o argumento da macro entre parênteses:
FOO((std::map<int, int>), map_var);
O problema é então que o parâmetro permanece entre parênteses dentro da expansão da macro, o que impede que seja lido como um tipo na maioria dos contextos.
Um bom truque para contornar isso é que em C ++, você pode extrair um nome de tipo de um nome de tipo entre parênteses usando um tipo de função:
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);
Como a formação de tipos de função ignora parênteses extras, você pode usar esta macro com ou sem parênteses, onde o nome do tipo não inclui uma vírgula:
FOO((int), int_var);
FOO(int, int_var2);
Em C, é claro, isso não é necessário porque os nomes dos tipos não podem conter vírgulas fora dos parênteses. Portanto, para uma macro de linguagem cruzada, você pode escrever:
#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