Boost logo

Boost :

From: Vesa Karvonen (vesa.karvonen_at_[hidden])
Date: 2001-12-18 06:47:57


From: "David Abrahams" <david.abrahams_at_[hidden]>
> If I have to
> debug code generated by the preprocessor library,

Debugging of preprocessor generated code is certainly a problem on current
compilers/debuggers. I wouldn't necessarily recommend using the preprocessor
library for initial implementation of library primitives. Instead you should
first implement a small scale version without the preprocessor and after
debugging and understanding the code thoroughly you can choose to extend its
usability range (e.g. increase parameter range from 3 to 16) and make it
configurable by using the preprocessor library.

Sometimes you need to step into robust library routines to track down bugs in
not so robust code. The need for this can be somewhat reduced with a proper
amount of DbC, so that you really don't have to step into library routines as
the preconditions prevent it.

> or even understand the
> source, I'm going to have a hard time.

I think that a big part of the readability problem is caused by the 18
character prefix:

  BOOST_PREPROCESSOR
  123456789012345678

Without the prefix, the code is much easier to read. Consider, for example, a
nearly arbitrarily chosen preprocessor library snippet (I had to reformat it
because the lines were too long):

#define BOOST_PREPROCESSOR_ENUM_PARAMS_WITH_A_DEFAULT(N,P,D)\
  BOOST_PREPROCESSOR_REPEAT(N,BOOST_PREPROCESSOR_PARAM_WITH_A_DEFAULT,(P,D))

#define BOOST_PREPROCESSOR_PARAM_WITH_A_DEFAULT(I,PD)\
 BOOST_PREPROCESSOR_COMMA_IF(I) BOOST_PREPROCESSOR_CAT(\
  BOOST_PREPROCESSOR_TUPLE_ELEM(2,0,PD),I) = \
   BOOST_PREPROCESSOR_TUPLE_ELEM(2,1,PD)

And then consider the same code without the prefixes:

#define ENUM_PARAMS_WITH_A_DEFAULT(N,P,D)\
  REPEAT(N,PARAM_WITH_A_DEFAULT,(P,D))

#define PARAM_WITH_A_DEFAULT(I,PD)\
 COMMA_IF(I) CAT(TUPLE_ELEM(2,0,PD),I)=TUPLE_ELEM(2,1,PD)

I think that understanding preprocessor code is not really harder than
understanding any other code. It is just different and it takes some time to
get used to.

When you write preprocessor code, try as much as possible to avoid writing
#defines inline with regular C++ code. The preprocessor directives are very
different from the regular C++ code you are trying to generate and this easily
makes the code difficult to read. So, instead try as much as possible to
design reusable parameterized macros for your common source code repetition
problems. The parameter enumeration macros are like this. The kind of
repetition is common and the macros solve the problem in a quite readable
manner.

> So far, I've been using some Python
> scripts to generate readable, debuggable C++ when neccessary. I also have
> had some practical problems using PREPROCESSOR with Metrowerk's broken
> preprocessor. So, I guess I'm trying to figure out when/where I'd want to
> use Boost.PREPROCESSOR instead of my Python scripts.

The parameter list enumeration (ENUM_PARAMS() and variations) macros are
probably the easiest to understand and use from client perspective. The
parameter enumeration macros are quite useful while implementing template
metaprogramming primitives.

Also, CAT() and STRINGIZE() are easy to understand and use when needed. I
think that both of them are implemented more than once in Boost. I would
probably want to see CAT() and STRINGIZE() in the standard C and C++
libraries.

The next step is to start using REPEAT[_2ND]() to avoid excessive repetition.
This certainly takes some more time to get used to simply because you need to
start writing your own macros.

After a while you'll bump into a repetition problem which requires some
arithmetic. This is when the rest of the library becomes useful.

However, if you are comfortable with Python scripts, then by all means, don't
stop using them. For complicated source code generation I'd definitely use
some external tool. For rather simple repetition I'd use the preprocessor
library, because then I don't have to complicate the build process.


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