Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2006-01-14 05:14:52


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Bradley Smith

Hi Brad.
Okay, a little more time now...

> I'm new to boost but I did search the group as thoroughly as
> I could before asking this. Anyway, the documentation gives
> this as an example:
>
> #include <boost/preprocessor/cat.hpp>
> #include <boost/preprocessor/repetition/repeat_from_to.hpp>
>
> #define DECL(z, n, text) BOOST_PP_CAT(text, n) = n;
>
> BOOST_PP_REPEAT_FROM_TO(5, 10, DECL, int x)
> /*
> expands to:
> int x5 = 5; int x6 = 6; int x7 = 7;
> int x8 = 8; int x9 = 9;
> */
>
> What confuses me is that BOOST_PP_REPEAT_FROM_TO expands to
> BOOST_PP_CAT and so does DECL yet after expanding DECL to
> BOOST_PP_CAT the (comeau) preprocessor continues to expand
> BOOST_PP_CAT to give the desired result.

#define A() B
#define B() ...

A()()

The difference between the documentation example an your example below boils
down to the above situation. The invocation of 'B' is not geographically nested
in 'A', and therefore the context that disables 'A' is no longer active when 'B'
is expanded. REPEAT_FROM_TO works in roughly the same way. The macro itself is
an object-like macro that expands to a different macro name, similar to what 'A'
does above, except that it is deducing which of several macros should be used
(it is detecting the presence or lack of disabling contexts). For example, say
that you have...

#define REPEAT_FROM_TO_1(a, b, macro, data) // ...
#define REPEAT_FROM_TO_2(a, b, macro, data) // ...
#define REPEAT_FROM_TO_3(a, b, macro, data) // ...

IOW, three (in this example) distinct copies of the REPEAT_FROM_TO
implementation. Now, say that you use one of them:

#define MACRO(z, n, data) // ...

REPEAT_FROM_TO_1(1, 5, MACRO, ~)

Now, when 'MACRO' gets invoked by REPEAT_FROM_TO_1, the disabling context on
REPEAT_FROM_TO_1 is still active, and thus REPEAT_FROM_TO_1 cannot be used by
'MACRO'--so it must use REPEAT_FROM_TO_2 instead. The library can detect
whether or not the disabling context on (e.g.) REPEAT_FROM_TO_1 is active
(similarly with REPEAT_FROM_TO_2, etc.). So, what it does is define an
interface macro that redirects to one of these three implementations. This
interface is really an object-like macro, though a use of it looks like an
invocation of a function-like macro:

#define REPEAT_FROM_TO [choose to 'return' REPEAT_FROM_TO_1, _2, or _3]

 REPEAT_FROM_TO (1, 5, MACRO, ~)
|______________|

This first part expands by itself (the argument list is irrelevant to it) to
REPEAT_FROM_TO_1, _2, or _3. Whichever macro name it "returns" expands against
the argument list, and you have the same situation as the 'A' 'B' example above.
The invocation of (e.g.) REPEAT_FROM_TO_1 against the argument list is not
nested in either REPEAT_FROM_TO or any of the macros that it uses to derive its
result.

> However, in the
> following code:
>
> #define CONCAT_1(a, b) CONCAT_1_D(a, b)
> #define CONCAT_1_D(a, b) a ## b
> #define CONCAT_2(a, b) CONCAT_2_D(a, b)
> #define CONCAT_2_D(a, b) a ## b
> #define AB(c, x, y) CONCAT_ ## c(x,y)

This example, OTOH, is like

#define A() B()
#define B() ...

...rather than like the 'A' 'B' example above. Here, the invocation of 'B' is
geographically nested in the replacement list of 'A'. Thus, when 'B' is
expanded, the disabling context of 'A' is still active and any further uses of
'A' won't expand.

> Can someone explain what I'm not understanding here (this
> isn't in my usual field of work)?

Does that help?

Regards,
Paul Mensonides


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