Boost logo

Boost :

From: Oliver Kullmann (O.Kullmann_at_[hidden])
Date: 2006-02-13 13:22:32


Hello,

yesterday I spent the day with my first application of
the Boost Preprocessor library:

Given two sequences A and B (according to the Boost
Preprocessor datastructure definition), I want
to create a nested switch statement, the outer
switch running through the constants in A, the inner
loops running through B.

Piece of cake: Just apply BOOST_PP_SEQ_FOR_EACH
two times.

Didn't work, because the preprocessor when evaluating
a macro M will suspend the definition of M during the
evaluation (thus "no recursion"). Unfortunately, I
didn't know this, so I had to find it out the hard way.

First of all I think here the documentation of the library
doesn't reach its full potential yet: I tried first to
read through "Topics", but found all examples contrived
and complicated (couldn't find a single plain example),
and thus I skipped that and went to Reference, where
I found BOOST_PP_SEQ_FOR_EACH, making some still mysterious
remarks about "The next available BOOST_PP_FOR repetition."
etc. But at various places it somehow says that "reentry problems"
whatever this means are solved now. Only when looking it up
in the rationale of C99 I found a clear statement about the issue
(while the C++ standard somehow supposes you know already the
issue).

So a clear statement about the limitations of the looping constructions
*at each place* would help I would guess quite a few people trying to
use this library. (I believe documentation must be written so that
it can be entered in many ways, and not assuming you are reading it
from the start to the end --- redundancy is needed.)

Second of all it seems the current facilities in the library should
be enhanced (though I don't understand how FOR and FOR_r is supposed
to be used): BOOST_PP_SEQ_FOR_EACH is such a natural and easy thing,
the use of it should be promoted, while FOR and its derivates look
ugly. But it seems that the library favours FOR, and seems to envisage
a main loop using FOR, and only at the second level using FOR_EACH.

My solution was to convert the second sequence B into a list, and
use BOOST_PP_LIST_FOR_EACH for the inner loop. But it seems to me that this works is
pure chance, and with any change in the implementation of BOOST_PP_SEQ_FOR_EACH
or BOOST_PP_LIST_FOR_EACH (introducing a common macro) this solution
will break.

According to what I understand from the documentation, the natural solution,
offering for example BOOST_PP_SEQ_FOR_EACH_2, which uses macros guaranteed
not to occur in BOOST_PP_SEQ_FOR_EACH, has been deprecated in favour of
a more complicated solution. But it seems this more complicated solution
works only for one kind of loop, and not for others, and the documentation
seems so arcane that I don't have a clue how it could work (the typical
phenomenon, that the documentation wants to show off by presenting only
complicated examples, which show all sorts of templates, etc., and this
without saying what actually should by achieved --- good code solves one
problem at a time, and good documentation discusses one problem at a time).

So if the library offers a natural way of nesting BOOST_PP_SEQ_FOR_EACH,
then documenting this (directly, without solving other problems) would be good,
or otherwise adding BOOST_PP_SEQ_FOR_EACH_2 would help some users (actually,
just the presence of this second form would announce the underlying problem).

Sometimes less general but simpler solutions are preferable over more
general but complicated solutions.

Oliver

P.S. The situation with the preprocessor is complicated by the general silence
on this issue in the books. And quite amazing, how the library achieves
to squeeze out nearly a general purpose machine (but not with an infinite
tape :-)) from the preprocessor machinery, which seems to have been castrated
by the designers on purpose.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk