Opened 14 years ago
Closed 14 years ago
#2329 closed Bugs (invalid)
GCC preprocessing error
Reported by: | Owned by: | No-Maintainer | |
---|---|---|---|
Milestone: | Boost 1.37.0 | Component: | preprocessor |
Version: | Boost 1.36.0 | Severity: | Problem |
Keywords: | Cc: |
Description
#include "boost/preprocessor.hpp"
#define _NOP() #define _UL() _ #define _SC() ; #define CLASS( name ) class name #define STRUCT( name ) struct name
#define _PUBLIC() public #define _PRIVATE() private #define _PROTECTED() protected
#define DECLARE_MEMBER(r, d, mem) \
BOOST_PP_TUPLE_ELEM(2, 0, mem) BOOST_PP_TUPLE_ELEM(2, 1, mem) _SC()
#define DECLARE_ARG_CONSTRUCT(r, d, arg) \
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())
#define DECLARE_ARG_CONSTRUCT_INIT(r, d, arg) \
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())
#define DECLARE_T( lang_type, name, memeber_seq, member_access ) \
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) \ };
#define DEF_TN( t,n ) ((t,n))
Use in code: DECLARE_T( STRUCT, some, DEF_TN(int, a) DEF_TN(int, b) DEF_TN(int, c), _PUBLIC() )
Two compilers MSVC++ 2005 for Win platform and XCode 3.0 GCC for MacOSX platform
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 ; };
XCode GCC ― error: macro "BOOST_PP_EXPR_IIF" passed 3 arguments, but takes just 2
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.
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:
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:
use:
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:
You're also going to run into trouble with
member_access##:
because you can only concatenate with numbers and identifiers (i.e.[0-9A-Za-z_]
).member_access :
should be fine - no concatenation is required.