|
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