Da Klammern Winkel auch (oder treten in) die Vergleichsoperatoren darstellen können <
, >
, <=
und >=
können Makroerweiterung ignorieren keine Kommas innerhalb spitzen Klammern , wie es in Klammern der Fall ist. (Dies ist auch ein Problem für eckige Klammern und Klammern, obwohl diese normalerweise als ausgeglichene Paare auftreten.) Sie können das Makroargument in Klammern setzen:
FOO((std::map<int, int>), map_var);
Das Problem ist dann, dass der Parameter innerhalb der Makroerweiterung in Klammern bleibt, wodurch verhindert wird, dass er in den meisten Kontexten als Typ gelesen wird.
Ein guter Trick, um dies zu umgehen, besteht darin, dass Sie in C ++ einen Typnamen aus einem in Klammern gesetzten Typnamen mithilfe eines Funktionstyps extrahieren können:
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);
Da beim Bilden von Funktionstypen zusätzliche Klammern ignoriert werden, können Sie dieses Makro mit oder ohne Klammern verwenden, wenn der Typname kein Komma enthält:
FOO((int), int_var);
FOO(int, int_var2);
In C ist dies natürlich nicht erforderlich, da Typnamen keine Kommas außerhalb von Klammern enthalten dürfen. Für ein sprachübergreifendes Makro können Sie also schreiben:
#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