Boost logo

Boost Users :

Subject: Re: [Boost-users] Preprocessor Recursion
From: Edward Diener (eldiener_at_[hidden])
Date: 2013-10-27 10:46:53


On 10/25/2013 3:53 PM, Mitch Besser wrote:
> I'm trying to create a 'C' macro that will define and initialize static
> data.
>
> For example:
>
> STATIC_CONST_STRUCT
> (
> A, a,
> MEMBER_DATA(CONST_STR, a, "Hello, a")
> MEMBER_DATA(CONST_STR, b, "Hello, b")
> MEMBER_STRUCT
> (
> C, c,
> MEMBER_DATA(CONST_STR, d, "Hello, d")
> MEMBER_DATA(CONST_INT, e, 1)
> )
> );
>
> Would cause the 'C' preprocessor to create:
>
> static const struct A
> {
> CONST_STR a;
> CONST_STR b;
> struct C
> {
> CONST_STR d;
> CONST_INT e;
> } c;
> } =
> {"Hello, a", "Hello, b", {"Hello, d", 1}};
>
> If I could use C++, this would be easy, but I'm using 'C' and it would
> be very helpful to have the initialization along with the declaration.
>
> I can't quite figure out how to make this work. My macros stop
> expanding. I suspect the recursive nature of the problem having an
> arbitrarily deep nesting is why. If it helps, I do have a maximum depth
> for the nesting.
>
> I've tried reading the docs and learn more about recursion, but I can't
> seem to find a solution. I suspect I'm close.
>
> Here's what I have so far (not claiming this is a good solution, so feel
> free to suggest anything that would make this better):
>
> #define MEMBER_DATA_TAG 0
> #define MEMBER_STRUCT_TAG 1
>
> #define MEMBER_TAG(MEMBER) BOOST_PP_SEQ_ELEM(0, MEMBER)
>
> #define MEMBER_DATA_TYPE(MEMBER_DATA) BOOST_PP_SEQ_ELEM(1, MEMBER_DATA)
> #define MEMBER_DATA_NAME(MEMBER_DATA) BOOST_PP_SEQ_ELEM(2, MEMBER_DATA)
> #define MEMBER_DATA_VALUE(MEMBER_DATA) BOOST_PP_SEQ_ELEM(3,
> MEMBER_DATA)
>
> #define MEMBER_STRUCT_TYPE(MEMBER_STRUCT) BOOST_PP_SEQ_ELEM(1,
> MEMBER_STRUCT)
> #define MEMBER_STRUCT_NAME(MEMBER_STRUCT) BOOST_PP_SEQ_ELEM(2,
> MEMBER_STRUCT)
> #define MEMBER_STRUCT_MEMBER_SEQ(MEMBER_STRUCT)
> BOOST_PP_SEQ_ELEM(3, MEMBER_STRUCT)
>
> #define MEMBER_DATA(TYPE, NAME, VALUE)
> ((MEMBER_DATA_TAG)(TYPE)(NAME)(VALUE))
> #define MEMBER_STRUCT(TYPE, NAME, MEMBER_SEQ)
> ((MEMBER_STRUCT_TAG)(TYPE)(NAME)(MEMBER_SEQ))
>
> #define IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM)
> BOOST_PP_EQUAL(MEMBER_TAG(MEMBER_SEQ_ELEM), MEMBER_STRUCT_TAG)
>
> #define MEMBER_STRUCT_DECLARE(TYPE, NAME, MEMBER_SEQ)
> \
> struct TYPE
> \
> {
> \
> BOOST_PP_SEQ_FOR_EACH(MEMBER_ELEM_DECLARE,
> BOOST_PP_EMPTY(), MEMBER_SEQ) \
> } NAME
>
> #define MEMBER_ELEM_DECLARE(_r, _data, MEMBER_SEQ_ELEM) \
> BOOST_PP_IIF \
> ( \
> IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM), \
> MEMBER_STRUCT_DECLARE \
> ( \
> MEMBER_STRUCT_TYPE(MEMBER_SEQ_ELEM), \
> MEMBER_STRUCT_NAME(MEMBER_SEQ_ELEM), \
> MEMBER_STRUCT_MEMBER_SEQ(MEMBER_SEQ_ELEM) \
> ), \
> MEMBER_DATA_DECLARE \
> ( \
> MEMBER_DATA_TYPE(MEMBER_SEQ_ELEM), \
> MEMBER_DATA_NAME(MEMBER_SEQ_ELEM), \
> MEMBER_DATA_VALUE(MEMBER_SEQ_ELEM) \
> ) \
> );
>
> #define MEMBER_DATA_DECLARE(TYPE, NAME, VALUE) TYPE NAME
>
> #define MEMBER_VALUE_INIT(MEMBER_SEQ) \
> BOOST_PP_SEQ_FOR_EACH_I(MEMBER_VALUE_INIT_DECLARE,
> BOOST_PP_EMPTY(), MEMBER_SEQ);
>
> #define MEMBER_VALUE_INIT_DECLARE(_r, _data, i, MEMBER_SEQ_ELEM) \
> BOOST_PP_COMMA_IF(i) \
> BOOST_PP_IIF \
> ( \
> IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM), \
> {MEMBER_VALUE_INIT(MEMBER_SEQ_ELEM)}, \
> MEMBER_DATA_VALUE(MEMBER_SEQ_ELEM) \
> )
>
> #define STATIC_CONST_STRUCT(TYPE, NAME, MEMBER_SEQ) \
> static const MEMBER_STRUCT_DECLARE(TYPE, NAME, MEMBER_SEQ) = \
> { \
> MEMBER_VALUE_INIT(MEMBER_SEQ) \
> }
>
> Thanks.

If you use the tracing facility of the Boost.Wave driver you will be
able to see how your macros are expanded.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net