Parce que les supports d'angle peuvent également représenter (ou se produire dans) les opérateurs de comparaison <
, >
, <=
et >=
, l' expansion macro ne peuvent pas ignorer les virgules à l' intérieur crochets comme il le fait entre parenthèses. (C'est également un problème pour les crochets et les accolades, même si ceux-ci se présentent généralement sous forme de paires équilibrées.) Vous pouvez mettre l'argument de macro entre parenthèses:
FOO((std::map<int, int>), map_var);
Le problème est alors que le paramètre reste entre parenthèses dans le développement de la macro, ce qui l'empêche d'être lu comme un type dans la plupart des contextes.
Une astuce intéressante pour contourner ce problème est qu'en C ++, vous pouvez extraire un nom de type d'un nom de type entre parenthèses à l'aide d'un type de fonction:
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);
Étant donné que la formation des types de fonction ignore les parenthèses supplémentaires, vous pouvez utiliser cette macro avec ou sans parenthèses où le nom du type n'inclut pas de virgule:
FOO((int), int_var);
FOO(int, int_var2);
En C, bien sûr, ce n'est pas nécessaire car les noms de type ne peuvent pas contenir de virgules en dehors des parenthèses. Donc, pour une macro multilingue, vous pouvez écrire:
#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