With the C preprocessor you can have some kind of high-order macros. Something like this:
#define ABC(f) f(a) f(b) f(c)
#define XY(f) f(x) f(y)
#define CODE(x) foo_ ## x
ABC(CODE)
#undef CODE
#define CODE(x) bar_ ## x
XY(CODE)
#undef CODE
The output is:
foo_a foo_b foo_c
bar_x bar_y
Is there some trick to nest such iterations, to do something like this?
#define CODE(x) foo_ ## x
NEST(ABC, XY, CODE)
#undef CODE
So the output would be:
foo_ax foo_ay foo_bx foo_by foo_cx foo_cy
In particular, I'd like to have the definitions of ABC
and XY
independent from each other, so that I can still use ABC
stand-alone or maybe do even something like this:
#define CODE(x) foo_ ## x
NEST(XY, KLMN, ABC, CODE)
#undef CODE
For the record, here the solution:
#include <boost/preprocessor/seq.hpp>
#define ABC (a) (b) (c)
#define XY (x) (y)
#define CODE(r, prod) BOOST_PP_CAT(foo_, BOOST_PP_SEQ_CAT(prod))
BOOST_PP_SEQ_FOR_EACH_PRODUCT(CODE, (ABC) (XY))
Yields:
foo_ax foo_ay foo_bx foo_by foo_cx foo_cy
The C preprocessor and macros are one of the most useful elements for writing portable C/C++ code . It even can be used to completely different purposes, like text processing. However, it suffers one major drawback: it does not support nested macros expansion (put differently, macros within macros).
A nested macro instruction definition is a macro instruction definition you can specify as a set of model statements in the body of an enclosing macro definition. This lets you create a macro definition by expanding the outer macro that contains the nested definition.
#ifdef directives can be nested, however, all directives in a given logical level must exist in a single file. The following sample code showing use of the #ifdef directive chain with nested #ifdefs. The expression #ifndef Name evaluates to true in Name has not been #defined.
The #ifdef identifier statement is equivalent to #if 1 when identifier has been defined. It's equivalent to #if 0 when identifier hasn't been defined, or has been undefined by the #undef directive.
The Boost Preprocessor Library offers several macros that can do this out of the box.
BOOST_PP_SEQ_FOR_EACH_PRODUCT will iterate over the cartesian products of two or more lists encoded in the form (x) (y) (z)
(which are known as sequences is the library's parlance).
BOOST_PP_LIST_FOR_EACH_PRODUCT will do the same for lists encoded as (x, (y, (z, NIL)))
.
It's trivial to convert the X macro iteration to a "sequence" like this:
#define LIST_TO_SEQ(X) (X)
ABC(LIST_TO_SEQ)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With