Search code examples
c++boostc-preprocessorboost-preprocessor

What BOOST_PP_AUTO_REC does?


I met in boost define

# define BOOST_PP_ENUM BOOST_PP_CAT(BOOST_PP_ENUM_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))

Could anyone explain what BOOST_PP_AUTO_REC does? Can't find any description in documentation. What this macros actually for?


Solution

  • The BOOST_PP_AUTO_REC help deduces the recursion level used in Automatic Recursion, by performing a binary search using a predicate. The first argument is the predicate and the second is the size to be searched. The predicate will be called as pred(n), where pred is the predicate and n is the value.

    The search must be ordered, so all values for which the predicate returns 0 must come before all values for which the predicate returns 1.

    Since, the macro is used for Automatic Recursion, the predicate can not use any macro which employ automatic recursion.

    For example, the predicate for repeat is defined like this:

    # define BOOST_PP_REPEAT_P(n) BOOST_PP_CAT(BOOST_PP_REPEAT_CHECK_, BOOST_PP_REPEAT_ ## n(1, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_3, BOOST_PP_NIL))
    #
    # define BOOST_PP_REPEAT_CHECK_BOOST_PP_NIL 1
    # define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_1(c, m, d) 0
    # define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_2(c, m, d) 0
    # define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_3(c, m, d) 0
    

    So if BOOST_PP_REPEAT_1 is called recursively, it won't expand. Thus when it concats with BOOST_PP_REPEAT_CHECK_ it will expand to BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_1, which will expand to 0. However if BOOST_PP_REPEAT_1 is not being called recursively, then it will expand to BOOST_PP_NIL, which is then concated with BOOST_PP_REPEAT_CHECK_ to produce 1.

    So the predicate is setup to detect if one of the BOOST_PP_REPEAT_n macros can expand. Then BOOST_PP_AUTO_REC will perform a binary search to find the first one that can expand. In the case of BOOST_PP_REPEAT, it will only search across 4 recursion levels, but other macros such as BOOST_PP_WHILE has a recursion depth up to 256.