Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-05-12 22:52:37


> ----- Original Message -----
> From: "Paul Mensonides"
>
> I don't even know Python for that matter--it is not my area.
> > > > Without better support for expansion and debuggable output, the
> > > preprocessor
> > > > library is seriously lacking.
>
> I am very interested. Debuggability is of prime importance
> for me and is one of the main reason why I chose not to
> use Boost::PP when I coded Phoenix. Please bring me up
> to speed. How is it debuggable?
>
> --Joel

The main problem with large expansion with the Boost.Preprocessor library is
that it uses macros only. Basically, what that means is that *everything* come
out on one (possibly huge) line.

What I'm working on uses the inclusion mechanism as well, which causes the
preprocessor output to be significantly cleaner--it also has the side benefit of
being faster on EDG-based compilers.

I'll give you a small (very small) example that uses it:

// sample.h

#if !defined IS_ITERATING

    #ifndef SAMPLE_H
    #define SAMPLE_H

    ??=include ENABLE(iterate.hxx)

        #define BOUND 10
        #include SET_UBOUND()

        #define FILENAME_1 "sample.h"
        #include ITERATE()

    ??=include DISABLE(iterate.hxx)

    #endif

#else // i.e. IS_ITERATING

template<LIST_CLASS(FILE_ARG(), T)>
inline void sample( LIST_PARAMS(FILE_ARG(), NIL, T, NIL, p) );

#endif

// end sample.h

When preprocessed, this will produce:

template<class T1>
inline void sample(T1 p1);

template<class T1, class T2>
inline void sample(T1 p1, T2 p2);

// etc.

The key point is that preprocessor output is actually on separate lines like the
above. So if I made a syntax error, the error message would be significantly
better.

Basically, what is happening is that the iteration mechanism is treating a
'file' like a macro, and 'macros' like parameters to the file. Currently, the
library supports five levels of iteration. The runtime analog to:

for (int a = lb_1; a <= ub_1; ++a) {
    for (int b = lb_2; b <= ub_2; ++b) {
        for (int c = lb_3; c <= ub_3; ++c) {
            for (int d = lb_4; d <= ub_4; ++d) {
                for (int e = lb_5; e <= ub_5; ++e) {
                    // ...
                }
            }
        }
    }
}

So implementing a function_traits like this (stripped down) is fairly
straightforward:

template<class> struct function_traits;

template<class R> struct function_traits<R ()> {
    typedef R return_type;
};

template<class R, class T1> struct function_traits<R (T1)> {
    typedef R return_type;
    template<int I, int Dummy = 0> struct parameter;
    template<int Dummy> struct parameter<0, Dummy> {
        typedef T1 type;
    };
};

template<class R, class T1, class T2> struct function_traits<R (T1, T2)> {
    typedef R return_type;
    template<int I, int Dummy = 0> struct parameter;
    template<int Dummy> struct parameter<0, Dummy> {
        typedef T1 type;
    };
    template<int Dummy> struct parameter<1, Dummy> {
        typedef T2 type;
    };
};

// etc. etc.

The above only uses two levels of iteration, and it uses macro recursion to
generate things like:

class T1, class T2, ...

etc.

Does that help?

Paul Mensonides


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