|
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