|
Boost : |
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-05-27 18:49:17
From: "David Abrahams" <david.abrahams_at_[hidden]>
> > What do you Boosters think? Any feedback would be helpful
>
> Well, I think it's really cool. However, not being much of a PP
> metaprogrammer, I'd really like to see some more comments in the code you
> posted so I can understand how it works.
The VERIFY_CONCAT_1ST macro simply attempts to use CONCAT_1ST. If CONCAT_1ST is
'already in use' it won't expand. This gives two possible results:
CONCAT_1ST(RES_, 1) and RES_1. PRIVATE_CONCAT then concatenates CONCAT_ to that
and applies the empty parenthesis to the result. This will yield either
CONCAT_RES_1() or CONCAT_CONCAT_1ST(a, b)(). CONCAT_RES_1 simply expands to
CONCAT_1ST and returns from the mechanism. CONCAT_CONCAT_1ST(a, b) expands to a
dummy macro to use the () on. (The mechanism uses the () so it can reuse
PRIVATE_CONCAT.) The dummy macro expands to VERIFY_CONCAT_2ND() and the process
is repeated until a CONCAT_xxx is returned or some error message. It uses an
'in-and-out' method like CONCAT()(a, b) so that whatever CONCAT_xxx macro is
returned is still valid for use. CONCAT() is called and expanded, everything
that was inside it no longer matters, and it returns a viable CONCAT_xxx
macro-name which is provided with the arguments (a, b).
# define VERIFY_CONCAT_1ST() PRIVATE_CONCAT(CONCAT_, CONCAT_1ST(RES_, 1))()
# define CONCAT_RES_1() CONCAT_1ST
# define CONCAT_CONCAT_1ST(a, b) DUMMY_CONCAT_1ST
# define DUMMY_CONCAT_1ST() VERIFY_CONCAT_2ND() // CONCAT_2ND
# define VERIFY_CONCAT_2ND() PRIVATE_CONCAT(CONCAT_, CONCAT_2ND(RES_, 2))()
# define CONCAT_RES_2() CONCAT_2ND
# define CONCAT_CONCAT_2ND(a, b) DUMMY_CONCAT_2ND
# define DUMMY_CONCAT_2ND() VERIFY_CONCAT_3RD() // CONCAT_3RD
# define VERIFY_CONCAT_3RD() PRIVATE_CONCAT(CONCAT_, CONCAT_3RD(RES_, 3))()
# define CONCAT_RES_3() CONCAT_3RD
# define CONCAT_CONCAT_3RD(a, b) DUMMY_CONCAT_3RD
# define DUMMY_CONCAT_3RD() (ERROR_NO_AVAILABLE_CONCAT)
# define CONCAT() VERIFY_CONCAT_1ST()
> It looks like you are applying an extra level of indirection (i.e. macro
> invocation) to get the library to adjust its recursion level automatically.
> Is there a performance penalty?
Yes, but for a small example like this it is insignificant. I need to test it
in a way that uses it *heavily*--which is not easy :). The good part about it,
though, is that it makes macros that use it 'self-adjust'--which is extremely
nice. Also, even though you may get a really long a terrible error message if
something goes wrong in a more significant usage, you can still scan the output
for ERROR_ ....
> Also, in what way are you using the preprocessor's own limitations against
> it?
I'm banking on the fact that the preprocessor cannot recurse. Therefore you
have to have separate 'identical' implementations is several places--which
causes the interface to change (i.e. BOOST_PP_REPEAT, BOOST_PP_REPEAT_2ND,
etc.). Fortunately, the limitation itself provides the answer.
Also, using something like this, I'm thinking that the logical operations (==,
!=, <, etc.) could be reimplemented in a much more efficient manner--but I'm
getting ahead of myself.
Paul Mensonides
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk