Search code examples
c++visual-c++boostmacrosboost-preprocessor

Are two-dimensional sequences possible with Boost.Preprocessor?


Boost.PP Sequences are limited to 256 elements. To work around this, I want to use two-dimensional sequences, or a sequence of sequences, which would be defined like this:

((0)(1)(2)...(255))((256)(257))

Now, to supply a BOOST_PP_SEQ_FOR-like algorithm, I want to nest two of them like so:

//Inner loop
#define ELEM_ID_OP(_, func, elem) func(elem)
#define FOR_ELEM(func, seq) \
    BOOST_PP_SEQ_FOR_EACH(ELEM_ID_OP, func, seq)

//Outer loop
#define SEQ_ID_OP(_, func, seq) FOR_ELEM(func, seq) 
#define FOR_SEQ(func, multiseq) \
    BOOST_PP_SEQ_FOR_EACH(SEQ_ID_OP, func, multiseq)

//Testing function
#define MYFUNC(arg) \
    const int arg = 0;

FOR_ELEM(MYFUNC, (Zero)(One)(Two)) //works like a charm

FOR_SEQ(MYFUNC, ((zero)(one)(two))) //doesn't :(

On the second one, I'm getting multiple errors about undeclared identifiers:

error C2065: 'ELEM_ID_OP' : undeclared identifier
error C2065: 'MYFUNC' : undeclared identifier
error C2065: 'zero' : undeclared identifier
error C2065: 'one' : undeclared identifier
error C2065: 'two' : undeclared identifier

Does this mean that the maximum recursion depth of my compiler is reached so the macros ELEM_ID_OP and MYFUNC are not expanded anymore? Or is there an implementation detail in Boost.PP that prevents this from working? Is there a workaround for this?

I'm using VC++2013, if that helps.


Solution

  • Boost.Preprocessor cannot do the nested SEQ_FOR_EACH. If you were using a decent preprocessor, you could use Chaos which can do such arbitrary nesting (though it is not needed for just a SEQ_FOR_EACH as the sequence length is unrestricted in Chaos).

    For something so simple, you could do it directly with VC++ with something like

    #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
    #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
    
    #define A(id, value) const int id = value; B
    #define B(id, value) const int id = value; A
    #define A0
    #define B0
    
    #define C(bseq) CAT(A bseq, 0)
    
    C(
        (zero, 0)
        (one, 1)
        (two, 2)
    )
    
    #undef A
    #undef B
    #undef A0
    #undef B0
    #undef C