Ponieważ nawiasy kątowe mogą również reprezentować (lub występować w) porównanie Operatory <
, >
, <=
i >=
, rozszerzenie makr nie może zignorować przecinków w nawiasach ostrych, podobnie jak w nawiasach. (Jest to również problem dla nawiasach kwadratowych i szelki, chociaż te występują zwykle jako wyważone par.) Można załączyć makro argument w nawiasach:
FOO((std::map<int, int>), map_var);
Problem jest wtedy, że parametr pozostaje w nawiasach wewnątrz makra rozszerzenie, które uniemożliwia odczytanie go jako typ w większości kontekstów.
Miła trik obejścia tego jest to, że w języku C++, można wyodrębnić TypeName od A nawiasach nazwy typu użyciu funkcja Typ:
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);
Ponieważ tworząc typy funkcyjne ignoruje dodatkowych nawiasów, można użyć tego makra z lub bez nawiasów gdzie nazwa typu nie zawiera przecinek:
FOO((int), int_var);
FOO(int, int_var2);
w C, oczywiście, nie jest to konieczne, ponieważ nazwy typu nie może zawierać przecinki poza nawiasami. Tak więc, na makro cross-językowego można napisać:
#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
Zgaduję, że musisz uciec od postaci, które mają znaczenie, aby były literałami. – Jite
Przynajmniej w C++, możesz umieścić typedef wszędzie, więc nie jestem pewien, dlaczego mówisz, że musi być "wcześniej". –