Terje Slettebų wrote: > Is there some way (using PP-lib, or whatever), to pass a template-id > with more than one parameter (thus, it contains at least one comma), > to a macro? > > E.g.: > > #define TEST(a) test<a> t; > > TEST(std::pair<char,int>) // Won't work > > Maybe some sort of variation of BOOST_PP_IDENTITY: > > #define BOOST_PP_IDENTITY1(a) a > #define BOOST_PP_IDENTITY2(a,b) a,b > #define BOOST_PP_IDENTITY3(a,b,c) a,b,c > > etc. > > TEST(BOOST_PP_IDENTITY2(std::pair<char,int>)) // Now ok
I'll answer all three of these emails at once, since they are about the same thing. First, the above will cause problems, specifically problems like this: #define T1(a) T2(a) #define T2(a) test<a> t; #define IDENTITY2(a, b) a, b T1(IDENTITY2(std::pair<char, int>)) // error I.e. by the time that T2 is invoked, IDENTITY2 has already expanded, which yields too many arguments to T2. What we need is a general solution and a set of conventions for passing types. This is difficult without variadics to do with the preprocessor itself. Specifically, you have to use the core language: template<class T> struct wrap { typedef T type; }; template<class T> struct wrap<void (T)> { typedef T type; }; #define TYPE(x) wrap<void x>::type TYPE((int)) // okay TYPE((std::pair<char, int>)) // okay However, this has its own problems. Specifically, it is using function types to store the type--which is inside parentheses and therefore protected from the preprocessor. The use of function types with cause certain things to error: TYPE(( void )) // error TYPE(( int (int, int) )) // function type altered to pointer-to-function TYPE(( int[2] )) // array altered to pointer There is only one other language construct that might be of use here: pointers-to-members. Specifically, it is parenthesized, yet does not undergo promotion/alteration when used in a parameter list. However, it is intrusive: template<class> struct wrap; template<class T> struct wrap<void (T::*)(void)> { typedef T type; }; #define TYPE(x) wrap<void T(void)>::type TYPE(( std::pair<int, int>::* )) ^^^ Also, this cannot be used for non-class types--which can still have commas in them: template<class T, class U> struct typelist { typedef T head; typedef U tail; }; TYPE(( typelist<int, nil>::head::* )) // error So, without variadic macros, there is no "good" solution. Instead, you have to resort to hacks that require you to know the number of unbound commas in the type: #define IN(s, x) (s) x #define OUT(x) BOOST_PP_TUPLE_REM x #define M1(type) M2(type) #define M2(type) OUT(type) MACRO( IN(2, (std::pair<int, int>)) ) In other words, it is a complete pain to deal with them without variadics. *With* variadics, however, you can do a little better. Regards, Paul Mensonides _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost