BOOST_PP_COMMA, LPAREN,RPAREN delay eval?

I've looked at some of the uses of these, but can't figure out how to do the following. Using boost/preprocessor macros, I want to generate code something like: #include <boost/mpl/vector.hpp> #include <boost/mpl/at.hpp> using namespace boost::mpl; struct source { target my_target ; template<typename VecOfTypes> source ( VecOfTypes const& , at_c<VecOfTypes,0>::type a0 ) : my_target ( a0 ) {} template<typename VecOfTypes> source ( VecOfTypes const& , at_c<VecOfTypes,0>::type a0 , at_c<VecOfTypes,1>::type a1 ) : my_target ( a0 , a1 ) {} }; and use it as follows: typedef vector<int,float> int_float_typelist; source s0(int_float_typelist(),0); source s1(int_float_typelist(),0,2.5); I was planning on defining a macro, PP_CTOR_FORWARDER_OVERLOAD, to be used as: struct source { BOOST_PP_REPEAT(2,PP_CTOR_FORWARDER_OVERLOAD,(source, my_target)) }; However, I also would like to use it where instead of my_target(a0,a1), there might be super_type(new target(a0,a1)), in which case the tuple that was the last arg to BOOST_PP_REPEAT would contain left and right parens. However, when I tried: BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (source,auto_ptr<target> BOOST_PP_LPAREN() new target, BOOST_PP_RPAREN() )) I get: /usr/local/gcc-3.4-20040225/bin/g++ -ggdb -c -Wall -MMD -O0 -ggdb -E -I/home/evansl/prog_dev/boost-root.ln/boost_dev -I/home/evansl/prog_dev/boost-root.ln pp_ctor_forwarder.cpp |indent -st pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_0" requires 4 arguments, but only 2 given pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_1" requires 4 arguments, but only 2 given pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_2" requires 4 arguments, but only 2 given pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_0" requires 4 arguments, but only 2 given pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_1" requires 4 arguments, but only 2 given pp_ctor_forwarder.cpp:4:1: macro "BOOST_PP_TUPLE_ELEM_4_2" requires 4 arguments, but only 2 given # 1 "pp_ctor_forwarder.cpp" How can I cause the delay in evaluation of BOOST_PP_RPAREN and LPAREN to avoid these errors? Here is my current macro def: #include "boost/preprocessor/enum_params.hpp" #include "boost/preprocessor/inc.hpp" #include "boost/preprocessor/punctuation/comma_if.hpp" #include "boost/preprocessor/tuple/elem.hpp" #define PP_CTOR_FORWARDER_PARAM(z,n,_) \ BOOST_PP_COMMA_IF(n) at_c<VecOfTypes,n>::type BOOST_PP_CAT(a,n) #define PP_CTOR_FORWARDER_OVERLOAD(z,n,data) \ template< typename VecOfTypes > \ BOOST_PP_TUPLE_ELEM(4,0,data) \ ( VecOfTypes const& \ , BOOST_PP_REPEAT(BOOST_PP_INC(n), PP_CTOR_FORWARDER_PARAM, BOOST_PP_EMPTY) \ ) \ : BOOST_PP_TUPLE_ELEM(4,1,data) \ BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), a ) \ BOOST_PP_TUPLE_ELEM(4,2,data) \ {} TIA.

-----Original Message----- [mailto:boost-bounces@lists.boost.org] On Behalf Of Larry Evans Subject: [boost] BOOST_PP_COMMA, LPAREN,RPAREN delay eval?
BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (source,auto_ptr<target> BOOST_PP_LPAREN() new target, BOOST_PP_RPAREN() ))
Yeah, this will definitely fail because the data argument will immediately expand to "(source, auto_ptr<target>(new target,))". The left and right parentheses as well as the comma are operative preprocessing tokens to the preprocessor. The corresponding macros expand directly to them. That is fine, through one level of scanning, but not more: #define ID(x) x ID(BOOST_PP_LPAREN()) // okay, expands to: ( #define A(x) B(x) #define B(x) x A(BOOST_PP_LPAREN()) // error The Boost pp-lib cannot do the delay required to make this work properly. However, there are other methods of overloading an interface. Will something like this work instead? #include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/comparison/equal.hpp> #include <boost/preprocessor/control/expr_iif.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/seq/elem.hpp> #include <boost/preprocessor/seq/size.hpp> #define PP_CTOR_FORWARDER_PARAM(z, n, _) \ at_c<VecOfTypes, n>::type BOOST_PP_CAT(a, n) \ /**/ // data := // (source)(destination) // (source)(destination)(super-class) #define PP_CTOR_FORWARDER_OVERLOAD(z, n, data) \ template<typename VecOfTypes> \ BOOST_PP_SEQ_ELEM(0, data)( \ VecOfTypes const&, \ BOOST_PP_ENUM( \ BOOST_PP_INC(n), \ PP_CTOR_FORWARDER_PARAM, \ ~ \ ) \ ) \ : BOOST_PP_IIF( \ BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(data), 2), \ PP_CTOR_FORWARDER_OVERLOAD_A, \ PP_CTOR_FORWARDER_OVERLOAD_B \ )(n, data) \ /**/ #define PP_CTOR_FORWARDER_OVERLOAD_A(n, data) \ BOOST_PP_SEQ_ELEM(1, data)( \ BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), a) \ ) \ /**/ #define PP_CTOR_FORWARDER_OVERLOAD_B(n, data) \ BOOST_PP_SEQ_ELEM(2, data)( \ PP_CTOR_FORWARDER_OVERLOAD_A(n, data) \ ) \ /**/ BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (source)(my_target) ) BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (source)(new target)(auto_ptr<target>) ) (Note that two more helper macros are required because the Boost pp-lib doesn't do lazy evaluation. If it did, the two _A and _B helpers would be unnecessary.) Regards, Paul Mensonides

On 03/21/2004 04:48 PM, Paul Mensonides wrote: [snip]
The Boost pp-lib cannot do the delay required to make this work properly. However, there are other methods of overloading an interface. Will something like this work instead? [proposed code snipped] Regards, Paul Mensonides Yes! Thanks very much. With source: <-----------------cut here----------------------------- using namespace boost::mpl; struct target { target ( int ) { std::cout<<"target(int)\n"; }
target ( int , float ) { std::cout<<"target(int,float)\n"; } target ( int , float , target const& ) { std::cout<<"target(int,float,target const&)\n"; } target ( target const& ) { std::cout<<"target(target const&)\n"; } }; struct member_target { BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (member_target)(my_target) ) target my_target; }; struct super_auto_ptr_target : public std::auto_ptr<target> { BOOST_PP_REPEAT( 2, PP_CTOR_FORWARDER_OVERLOAD, (super_auto_ptr_target)(new target)(std::auto_ptr<target>) ) }; int main(void) { typedef vector<int,float> int_float_typelist; at_c<int_float_typelist,0l>::type i=0; ++i; std::cout<<"mt0\n"; member_target mt0(int_float_typelist(),0); std::cout<<"mt1\n"; member_target mt1(int_float_typelist(),0,2.5); std::cout<<"sapt0\n"; super_auto_ptr_target sapt0(int_float_typelist(),0); std::cout<<"sapt1\n"; super_auto_ptr_target sapt1(int_float_typelist(),0,2.5); return 0; }
-----------------------cut here--------------------------------- intel gets output:
/opt/intel_cc_80/bin/icc -g -o pp_ctor_forwarder.exe pp_ctor_forwarder.o running pp_ctor_forwarder ./pp_ctor_forwarder.exe mt0 target(int) mt1 target(int,float) sapt0 target(int) sapt1 target(int,float) however, g++ complains: /usr/local/gcc-3.4-20040225/bin/g++ -ggdb -c -Wall -MMD -O0 -ggdb -I/home/evansl/prog_dev/boost-root.ln/boost_dev -I/home/evansl/prog_dev/boost-root.ln -o pp_ctor_forwarder.o pp_ctor_forwarder.cpp pp_ctor_forwarder.cpp:49: error: `struct boost::mpl::at_c<VecOfTypes, 0l>::type' is not a type pp_ctor_forwarder.cpp:49: error: ISO C++ forbids declaration of `a0' with no type pp_ctor_forwarder.cpp:49: error: `struct boost::mpl::at_c<VecOfTypes, 0l>::type' is not a type pp_ctor_forwarder.cpp:49: error: `struct boost::mpl::at_c<VecOfTypes, 1l>::type' is not a type pp_ctor_forwarder.cpp:49: error: ISO C++ forbids declaration of `a0' with no type pp_ctor_forwarder.cpp:49: error: ISO C++ forbids declaration of `a1' with no type pp_ctor_forwarder.cpp:63: error: `struct boost::mpl::at_c<VecOfTypes, 0l>::type' is not a type pp_ctor_forwarder.cpp:63: error: ISO C++ forbids declaration of `a0' with no type pp_ctor_forwarder.cpp:63: error: `struct boost::mpl::at_c<VecOfTypes, 0l>::type' is not a type pp_ctor_forwarder.cpp:63: error: `struct boost::mpl::at_c<VecOfTypes, 1l>::type' is not a type pp_ctor_forwarder.cpp:63: error: ISO C++ forbids declaration of `a0' with no type pp_ctor_forwarder.cpp:63: error: ISO C++ forbids declaration of `a1' with no type pp_ctor_forwarder.cpp: In function `int main()': pp_ctor_forwarder.cpp:80: warning: passing `double' for converting 3 of `member_target::member_target(const VecOfTypes&, int, int) [with VecOfTypes = main()::int_float_typelist]' pp_ctor_forwarder.cpp:84: warning: passing `double' for converting 3 of `super_auto_ptr_target::super_auto_ptr_target(const VecOfTypes&, int, int) [with VecOfTypes = main()::int_float_typelist]' make: *** [pp_ctor_forwarder.o] Error 1 Again, thanks very much!

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Larry Evans
Yes! Thanks very much. With source:
however, g++ complains:
/usr/local/gcc-3.4-20040225/bin/g++ -ggdb -c -Wall -MMD -O0 -ggdb -I/home/evansl/prog_dev/boost-root.ln/boost_dev -I/home/evansl/prog_dev/boost-root.ln -o pp_ctor_forwarder.o pp_ctor_forwarder.cpp pp_ctor_forwarder.cpp:49: error: `struct boost::mpl::at_c<VecOfTypes, 0l>::type' is not a type pp_ctor_forwarder.cpp:49: error: ISO C++ forbids declaration of `a0' with no type
These are because of a missing typename. Instead of: #define PP_CTOR_FORWARDER_PARAM(z, n, _) \ at_c<VecOfTypes, n>::type BOOST_PP_CAT(a, n) \ /**/ It should be: #define PP_CTOR_FORWARDER_PARAM(z, n, _) \ typename at_c<VecOfTypes, n>::type BOOST_PP_CAT(a, n) \ /**/
Again, thanks very much!
You're welcome. Regards, Paul Mensonides
participants (2)
-
Larry Evans
-
Paul Mensonides