$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [Preprocessor] Adding variadic macros support
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2010-11-27 09:36:47
On Thu, 25 Nov 2010 08:42:37 -0500, Edward Diener wrote:
> You are right. Evidently the code is under CVS, but not under SVN ( yet
> ? ).
> 
> I will look at Chaos and see what is done.
You'll have to pull it out of the CVS repository.  The Subversion 
respository is not being used yet.  The library is complete, as of right 
now there are more than five hundred primary interface macros (i.e. not 
counting implementation macros).  There are more than two thousand 
interface macros if derivative macros are included (still not including 
implementation macros).
If you checkout from the CVS, there is a file $CHAOS_ROOT/built-docs/
headers.html that lists all of the headers in the library.  The first 
link (i.e. <chaos/preprocessor.h>) might be more useful for navigation.  
The reference documentation is complete (and extensive) except for a 
couple of macros that I added recently.  There are lots of examples 
(mostly contrived).  The topical documention is not complete, but feel 
free to ask me whatever you want.
Chaos' use of variadics is controlled by CHAOS_PP_VARIADICS.  This is 
normally set automatically based on whether the language supports 
variadics.  However, there is currently no usable definition of 
__cplusplus for it to work with.  Thus, by default, variadics are 
disabled in C++.  However, the macro CHAOS_PP_VARIADICS can be defined on 
the command line to override the automatic settings.  E.g. with GCC...
g++ -E -P -std=c++0x -I $CHAOS_ROOT -D CHAOS_PP_VARIADICS test.cpp
===== Requirement for a Compliant Preprocessor =====
The techniques used by Chaos' internals are *extremely* advanced.  Most 
of the time, they require the preprocessor to do *exactly* what it should 
do according to the standard(s).  Because of that, Chaos cannot be ported 
to broken preprocessors like MS (and putting workarounds in the source 
would defeat the purpose of Chaos even if such workarounds were possible).
I believe that GCC, EDG-based compilers, and Wave are 100% usable.  There 
are a few others that are mostly usable as well as a few tools that have 
internal (custom) preprocessor implementations that are 100% usable 
also.  In particular, VC++ is *not* usable.  I am not sure about Sun at 
the moment.
===== Notable Differences from the Boost pp-lib =====
The most obvious (considering the context) is support for variadics/
placemarkers from the ground up.  Probably more importantly, Chaos 
generalizes recursion and all higher-order constructs are reentrant 
without replication of their implementations.  As an example, take a look 
at the implementation of BOOST_PP_REPEAT compared to the following:
#define REPEAT(n, macro, ...) \
    REPEAT_S(CHAOS_PP_STATE(), n, macro, __VA_ARGS__) \
    /**/
#define REPEAT_S(s, n, macro, ...) \
    CHAOS_PP_IF(n)( \
        REPEAT_I, CHAOS_PP_EAT \
    )( \
        CHAOS_PP_OBSTRUCT(), CHAOS_PP_NEXT(s), \
        CHAOS_PP_DEC(n), macro, __VA_ARGS__ \
    ) \
    /**/
#define REPEAT_INDIRECT() REPEAT_S
#define REPEAT_I(_, s, n, macro, ...) \
    CHAOS_PP_EXPR_S _(s)(REPEAT_INDIRECT _()( \
        s, n, macro, __VA_ARGS__ \
    )) \
    CHAOS_PP_CALL(macro)()(s, macro, n, __VA_ARGS__) \
    /**/
#define MACRO(s, n, ...) \
    CHAOS_PP_COMMA_IF(n) class T ## n \
    /**/
CHAOS_PP_EXPR(REPEAT(
    5, MACRO, ?
))
===== Variadics as Data Structures =====
Over the course of development of Chaos, I rapidly discovered that the 
direct use of variadics as element sequences is only marginally useful 
(at best).  Variadics are better used for other things.  Let me clarify.  
Variadics as raw data structures are virulent.  They take over the 
interface of everything else by forcing particular argument orders and 
"stealing" the single variadic "argument".  As an obvious example, you 
can't have an algorithm that operates on two such data structures.
OTOH, variadics used indirectly in data structures are very useful (e.g. 
variadics sequences).  Even with tuples such that the size is not 
required to be known for element access.  Long story short, (...) is 
better than just ... for all kinds of reasons.
===== Lambdas/Binding =====
Chaos has a pretty heavyweight lambda engine.  For example (contrived),
#include <chaos/preprocessor.h>
CHAOS_PP_EXPR(CHAOS_PP_ENUM(
    5,
    CHAOS_PP_PRIMITIVE_CAT_(class T, CHAOS_PP_ARG(1))
        CHAOS_PP_WHEN_(CHAOS_PP_ARG(1))(
            CHAOS_PP_CAT_(= T, CHAOS_PP_DEC_(CHAOS_PP_ARG(1)))
        )
))
...results in:
class T0, class T1 = T0, class T2 = T1, class T3 = T2, class T4 = T3
However, the problem with lambdas (with the preprocessor) is that they 
are considerably more expensive.  No matter how you do it, it requires 
some sort of interpretation--which is slower--and simply having a macro 
is usually clearer.  I've actually been considering their removal from 
Chaos for several years.
#define _(s, n) \
    class T ## n \
        CHAOS_PP_WHEN(n)(= CHAOS_PP_CAT(T, CHAOS_PP_DEC(n))) \
    /**/
CHAOS_PP_EXPR(CHAOS_PP_ENUM(5, _))
#undef _