Poiché staffe angolari possono anche rappresentare (o verificarsi) gli operatori di confronto <
, >
, <=
e >=
, macro espansione non può ignorare virgole all'interno angolari come appare tra parentesi. (Questo è anche un problema per le parentesi quadre e le parentesi graffe, anche se di solito si presentano come coppie bilanciate.) Puoi racchiudere l'argomento macro tra parentesi:
FOO((std::map<int, int>), map_var);
Il problema è quindi che il parametro rimane tra parentesi all'interno dell'espansione della macro, il che impedisce che venga letto come un tipo nella maggior parte dei contesti.
Un bel trucco per risolvere questo problema è che in C ++ puoi estrarre un nome di tipo da un nome di tipo tra parentesi usando un tipo di funzione:
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);
Poiché la formazione dei tipi di funzione ignora le parentesi aggiuntive, puoi utilizzare questa macro con o senza parentesi in cui il nome del tipo non include una virgola:
FOO((int), int_var);
FOO(int, int_var2);
In C, ovviamente, questo non è necessario perché i nomi dei tipi non possono contenere virgole fuori parentesi. Quindi, per una macro multilingue puoi scrivere:
#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