
Boost : 
From: David Abrahams (david.abrahams_at_[hidden])
Date: 20020413 13:33:20
 Original Message 
From: "Andrei Alexandrescu" <andrewalex_at_[hidden]>
> The implementation of count_if as a library artifact is largely
> irrelevant. As long as a library function respects an interface, the
> library user can only appreciate a more sophisticated implementation.
> I understand we are discussing count_if as an example of typical
> implementation of a userdefined algorithm.
>
> Again, let me post some simple measurements of the two variants of
> count_if.
>
> The count_if implementation using mpl has 34 lines, defines 3 new
> types, 1 new namespace, and relies on 5 artifacts defined elsewhere.
>
> The countif that works only for dottypelists has 15 lines, defines 1
> new type, and does not rely on any other artifacts than the typelist
> itself.
>
> This being said, my argument on the simplicity of the patternmatching
> implementation of count_if is based on the following points:
>
> 1. Show the sheer code to a C++ programmer. For completeness' sake, I
> appended the code at the end of this post.
>
> 2. 15 < 34
>
> 3. 1 < 3
>
> 4. 0 < 1
>
> 5. 1 < 5
Yes, and you can write the simple dottypelist example using an MPL
typelist, nearly as easily... if you're willing to give up portability,
efficiency on large sequences, and flexibility. Aleksey's example shows
how to write a "generic" countif. The dottypelist example is
essentially nonpolymorphic (in the compiletime world). There's
definitely a place for that sort of code  most people, I daresay, are
not writing generic libraries. However, I don't think it's a longterm
win for MPL documentation to stress techniques for writing
typelistspecific algorithms when it provides such useful tools for
generic algorithms.
> Several people have repeatedly asked for selfcontained, sensical
> examples demonstrating that using the style pioneered by MPL leads to
> a good solution. I believe this is reasonable to ask for.
I agree; unfortunately all of the really heavyduty examples I've
generated which absolutely /need/ the abstractions of MPL in order to be
manageable are someone else's proprietary code. However, I think the MPL
rewrite of your GenScatterHierarchy is a good simple example. I
purposely left in all the comments and namespace qualifications just to
make this as verbose as possible. I did allow myself the small luxury of
using boost::mpl::apply<F,...> instead of F::template apply<...>.
// warning, untested
// The product of GenScatterHierarchy will always be one of these,
// with leaves being the classes in the type list.
template <class L, class R>
struct InheritTwo : public L , public R
{
typedef L Left;
typedef R Right;
};
// F is the transformation that will be bound into
// this function object and applied to each element;
// think of this as a parameterized function adaptor.
template <class F>
struct inherit_transformed
{
// This is the function object's operator()()
template <class Product, class Element>
struct apply
{
// first transform the type
typedef typename boost::mpl::apply<F,Element>::type transformed;
// This is the return value: we inherit from the
// current element and everything accumulated so far
typedef InheritTwo<transformed_type, Product> type;
};
};
// Now we can define GenScatterHierarchy
template <class Sequence, class Transformation>
struct GenScatterHierarchy
: boost::mpl::fold<
Sequence, EmptyType, inherit_transformed<Transformation>
>
{
};
Note that find_if is a bit artificially biased away from MPL idioms,
since it manipulates integral constants, and MPL adds a uniformity layer
to make them look like types.
Dave
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk