Boost C++ Libraries: Ticket #2329: GCC preprocessing error https://svn.boost.org/trac10/ticket/2329 <p> #include "boost/preprocessor.hpp" </p> <p> #define _NOP() #define _UL() _ #define _SC() ; #define CLASS( name ) class name #define STRUCT( name ) struct name </p> <p> #define _PUBLIC() public #define _PRIVATE() private #define _PROTECTED() protected </p> <p> #define DECLARE_MEMBER(r, d, mem) \ </p> <blockquote> <p> BOOST_PP_TUPLE_ELEM(2, 0, mem) BOOST_PP_TUPLE_ELEM(2, 1, mem) _SC() </p> </blockquote> <p> #define DECLARE_ARG_CONSTRUCT(r, d, arg) \ </p> <blockquote> <p> BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg)_UL() BOOST_PP_EXPR_IF(BOOST_PP_LESS_EQUAL(r,d), BOOST_PP_COMMA()) </p> </blockquote> <p> #define DECLARE_ARG_CONSTRUCT_INIT(r, d, arg) \ </p> <blockquote> <p> BOOST_PP_TUPLE_ELEM(2, 1, arg) ( BOOST_PP_TUPLE_ELEM(2, 1, arg)_UL() ) BOOST_PP_EXPR_IF(BOOST_PP_LESS_EQUAL(r,d), BOOST_PP_COMMA()) </p> </blockquote> <p> #define DECLARE_T( lang_type, name, memeber_seq, member_access ) \ </p> <blockquote> <p> lang_type(name) { \ name ( \ BOOST_PP_SEQ_FOR_EACH( DECLARE_ARG_CONSTRUCT, BOOST_PP_SEQ_SIZE(memeber_seq), memeber_seq ) \ ) : \ BOOST_PP_SEQ_FOR_EACH( DECLARE_ARG_CONSTRUCT_INIT, BOOST_PP_SEQ_SIZE(memeber_seq), memeber_seq ) \ {} \ member_access##: \ BOOST_PP_SEQ_FOR_EACH( DECLARE_MEMBER , _NOP(), memeber_seq) \ }; </p> </blockquote> <p> #define DEF_TN( t,n ) ((t,n)) </p> <p> Use in code: DECLARE_T( STRUCT, some, DEF_TN(int, a) DEF_TN(int, b) DEF_TN(int, c), _PUBLIC() ) </p> <p> Two compilers MSVC++ 2005 for Win platform and XCode 3.0 GCC for MacOSX platform </p> <p> Result: MSVC++ 2005 /W4 ― preprocessing succeful: struct some { some ( int a_ , int b_ , int c_ ) : a ( a_ ) , b ( b_ ) , c ( c_ ) {} public: int a ; int b ; int c ; }; </p> <p> XCode GCC ― error: macro "BOOST_PP_EXPR_IIF" passed 3 arguments, but takes just 2 </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/2329 Trac 1.4.3 Daniel James Tue, 16 Sep 2008 20:48:55 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/2329#comment:1 https://svn.boost.org/trac10/ticket/2329#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> Hi, this isn't a preprocessor bug, it's because of differences in the preprocessor implementations. The Visual C++ preprocessor doesn't follow the standard very closely, so without some care anything developed with it could easily not be portable. </p> <p> This really is something that should be sent to boost users, but I'll give you a few hints. First the problem you described is caused by your use of BOOST_PP_COMMA. It's getting expanded much earlier of gcc, and treated as a parameter seperator. A better way to do this would be something like: </p> <pre class="wiki">#define DECLARE_ARG_CONSTRUCT_INIT(r, d, arg) \ BOOST_PP_TUPLE_ELEM(2, 1, arg) ( BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, arg), _UL()) ) #define DECLARE_T ... \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ DECLARE_ARG_CONSTRUCT_INIT, BOOST_PP_SEQ_SIZE(memeber_seq), memeber_seq)) \ ... </pre><p> You'll notice I used BOOST_PP_CAT to concatenate the underscore. This is because you're relying on a bug in Visual C++ which concatenates the results of functions with the following token. So instead of: </p> <pre class="wiki">BOOST_PP_TUPLE_ELEM(2, 1, arg)_UL() </pre><p> use: </p> <pre class="wiki">BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, arg), _UL()) </pre><p> You've got a lot of pointless macros, such as _PRIVATE, _PUBLIC, _PROTECTED, _NOP and _UL. You can just use the keyword or symbol. Also names that start with an underscore and a capital are reserved, so you shouldn't use them. The code above becomes: </p> <pre class="wiki">BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, arg), _) </pre><p> You're also going to run into trouble with <code>member_access##:</code> because you can only concatenate with numbers and identifiers (i.e. <code>[0-9A-Za-z_]</code>). <code>member_access :</code> should be fine - no concatenation is required. </p> Ticket