Boost logo

Boost :

From: Mat Marcus (mmarcus_at_[hidden])
Date: 2001-12-12 13:25:24


    Aleksey> Overall, the tutorial is very good: you took exactly the
    Aleksey> direction Dave and I have been considering in our
    Aleksey> documentation effort, the technical side of presentation
    Aleksey> is impressive, and your writing is good :). The only
    Aleksey> general thing that I would like to note here is that some
    Aleksey> of the examples presented below can have a much simpler
    Aleksey> implementation; it's important to not over do it in terms
    Aleksey> of complexity while presenting the library to the
    Aleksey> first-time users :). On the other hand, simpler
    Aleksey> implementation would eliminate all these cool binders,
    Aleksey> composers and loops :).. hmm, seems like there is a need
    Aleksey> for a sequel tutorial :).

Thanks and agreed.

    Mat> But what is a "quoted metafunction"? Well, all MPL
    Mat> algorithms expect any of their arguments which happen to be
    Mat> metafunctions to be wrapped up in a struct. This technique is
    Mat> described in Czarnecki and Eisenecker's Generative
    Mat> Programming Book as an alternative to using template template
    Mat> parameters. I find it very helpful to think of these
    Mat> struct-wrapped metafunctions as "quoted". (Here I borrow the
    Mat> #' concept from common lisp. In common lisp, functions must
    Mat> be #' quoted to be passed as parameters to other
    Mat> functions. Another alternative would be to talk about the
    Mat> address of a metafunction but that seems more
    Mat> confusing. Perhaps someone will come up with a better name).

    Aleksey> In the boost::mpl documentation these are called
    Aleksey> "function classes" (by analogy with function objects), as
    Aleksey> opposite to (I hope) self-explanatory "class template
    Aleksey> metafunctions" (both of the concepts are particular
    Aleksey> instances of more general "metafunction" concept).

It's interesting that you suggest function class. At first I was
trying to describe the concept as a MetaFunctor, but I had trouble
justifying it to a colleague, so I used the #' analogy instead. It is
true that functors (or "function classes") can be built from
functions. Also operator() corresponds nicely to ::template apply. I
guess we could also populate the "wrapper struct" with additional
state information, so maybe it would be reasonable to think of it in
this way.

    Aleksey> This is one particular example that I would implement
    Aleksey> differently. Dave have already posted an example of
    Aleksey> implementation that is very close to what I am thinking
    Aleksey> of, but for the sake of demonstration of what I think is
    Aleksey> a "native MPL solution" :), here is my code:

    namespace aux {
    // auxiliary function class; will be applied to each element
    // in a sequence T0,T2,..Tn to produce the following multiple
    // inheritance hierarchy:
    // [type n] <+- [type n-1] .. <+- [type 0] <+- [empty]
    // +- F(Tn) +- F(T1) +- F(T0)

    template<typename F>
    struct node_generator
    {
        template<typename Base, typename T>
        struct apply
        {
            struct type // [type i]
                : Base // [type i-1] or [empty]
                , boost::mpl::unary_function<F,T>::type // F(Ti)
            {
            };
        };
    };
    } // namespace aux

                Aleksey> [...]

Yes. At first I tried to hide InheritTwo as well, but VC would not allow me
to get away with it :-).
 

    Aleksey> Again, this is something that I would implement
    Aleksey> differently:

    // a modified 'derived_class_generator' definition
    template<typename Types, typename F>
    struct derived_class_generator
    {
        struct empty
        {
            // NEW: provide the result class with 'field_list'
            // member, that will contain a list of
            // F(T0),F(T1),..,F(Tn) node types
                typedef typename boost::mpl::transform<
                  Types
                , boost::mpl::type_list<>
                , F
>::sequence field_list;
        };
        
        typedef typename boost::mpl::accumulate< // former for_each
              Types
            , empty
            , aux::node_generator<F>
>::type type;
    };

                Aleksey> [...]

Ahh, this is cleaner. I can see that I erred on the side of
compactness in my exposition. As Dave and you suggest a staged
tutorial would be better. The first chapter would be straightforward
and the second section could be written in a more compact, idiomatic
style.

    Aleksey> MSVC does compile this one :). I've uploaded the example
    Aleksey> file (derived_class_gen.cpp) to the MPL directory in the
    Aleksey> files section, if it's of any interest.

MSVC 6 and 7b2 still refuse to compile this for me. Perhaps its
because I'm using the 9/19 MPL? Also, I suggest that we add some
author attribution to derived_class_gen.cpp. In particular, the Loki
copyright notice should probably appear.

    Mat> * MPL needs documentation now. I believe some mpl naming
    Mat> conventions could be improved as well.

    Aleksey> Do you have any specific suggestions in mind (besides
    Aleksey> 'for_each' :)?

The other idea is that the MAKE_F_XXX macros could be more suggestive
once the right name for "function classes" is found.

    Mat> One particular problem is that small type_lists are padded
    Mat> with a lot of unused types.

    Aleksey> It's not exactly that. Type lists are not padded with
    Aleksey> unused types, these types are just a part of type list
    Aleksey> generator "signature", and that's why they appear in the
    Aleksey> error messages. One way to get rid of them is to inherit
    Aleksey> from type_list instead of typedef-ing it:
                Aleksey> [...]

Interesting.

Thanks,
 - Mat


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