Iteration limit in Boost Preprocessor
boost, boost-preprocessor, boost-test, c++
Solution
Good Lord.
It is quite possible that no one working on Boost.Test has considered what you're trying to do. The problem is not a compiler limitation, it's that `BOOST_PP_SEQ_FOR_EACH` is not reentrant and that `BOOST_CHECK_EQUAL` uses it. Because of this, using `BOOST_CHECK_EQUAL` inside `BOOST_PP_SEQ_FOR_EACH` is not possible. `BOOST_CHECK` works because it does not use `BOOST_PP_SEQ_FOR_EACH`.
I suggest this workaround:
#define CHECK_NODE_ORDER_INNER_LOOP(r, list, i, elem) \
BOOST_PP_LIST_FOR_EACH(CHECK_NODE_ORDER_ELEMENT, elem, \
BOOST_PP_SEQ_TO_LIST(BOOST_PP_SEQ_REST_N(i, list)))
I am aware that converting the sequence to a list for the sole purpose of nesting loops is rather ugly. In my defense, it is the least ugly approach that I can think of.
Problem
I am writing a unit test using the Boost::Test framework for a comparison function. For each test case I create a series of input elements and compare them pairwise to check the return value of the comparison function for each pair. I can either write it out manually or write a function. Writing a function is not good in unit tests because we get less useful information when there is a failure. Writing out each check manually results in very long unit tests. So I decided to use macros for iterating through the elements to be checked. It looks like this: ``` #define CHECK_NODE_LESS(less, more) do {\ BOOST_CHECK_EQUAL(compareQueueUnderTest((less), (more)), true); \ BOOST_CHECK_EQUAL(compareQueueUnderTest((more), (less)), false); \ } while (false) #define CHECK_NODE_ORDER_ELEMENT(r, elem1, elem2) CHECK_NODE_LESS(elem1, elem2); #define CHECK_NODE_ORDER_INNER_LOOP(r, list, i, elem) \ BOOST_PP_SEQ_FOR_EACH(CHECK_NODE_ORDER_ELEMENT, elem, \ BOOST_PP_SEQ_REST_N(i, list)) #define CHECK_NODE_ORDER(nodes) \ BOOST_PP_SEQ_FOR_EACH_I(CHECK_NODE_ORDER_INNER_LOOP, \ BOOST_PP_SEQ_TAIL(nodes), nodes) ``` In test cases with partial but no total ordering I use the `CHECK_NODE_LESS` macro on appropriate elements to check the elements that are ordered, and it works fine. In test cases with total ordering I use the `CHECK_NODE_ORDER` macro. For example: ``` CHECK_NODE_ORDER((node1)(rootNode1)(node2)(rootNode2)); ``` Now this one does not compile. The first thing I tested is to comment out the `CHECK_NODE_LESS` macro and run the preprocessor to see what is generated. It was what I expected: `CHECK_NODE_LESS` was called for the right elements. Then I reintroduced `CHECK_NODE_LESS` and ran the preprocessor to see what happens. The result was really ugly because of the macros used in Boost Test, but it could be seen that some macros are not expanded. Finally, I changed `CHECK_NODE_LESS` to the following and now it works fine: ``` #define CHECK_NODE_LESS(less, more) do {\ BOOST_CHECK(compareQueueUnderTest((less), (more))); \ BOOST_CHECK(!compareQueueUnderTest((more), (less))); \ } while (false) ``` I think the problem is that either there is some iteration limit in the Boost Preprocessor library that is exceeded when I use `BOOST_CHECK_EQUAL` together with the other macros, or there is a preprocessor depth limit in the compiler (I use Clang 3.4). What is this limit and how do I increase it?