Boost logo

Boost :

From: Douglas Paul Gregor (gregod_at_[hidden])
Date: 2003-01-23 10:51:50


On Thu, 23 Jan 2003, David Abrahams wrote:

> Douglas Paul Gregor <gregod_at_[hidden]> writes:
>
> > Why don't we have
> >
> > mpl::list<int, float, double, std::string> list_of_types;
> > for_each(list_of_types.begin(), list_of_types.end(), f);
> >
> > ?
> >
> > Then an unqualified for_each call can handle type sequences, heterogeneous
> > containers (e.g., tuple), and run-time sequences (e.g., vector). It's been
> > done before, elsewhere, so why don't we do it in MPL?
>
> It's clever, but I'm not sure what problem it's solving.

I mentioned this before and cited the paper "Static Data
Structures: Reconciling Template Metaprogramming and Generic Programming":
  http://aspn.activestate.com/ASPN/Mail/Message/1304415

The title says it all: we have generic programming and template
metaprogramming, and they complement each other nicely, but at the barrier
between them I feel that we have a kludge. MPL and STL are built on the
same abstractions, with similar naming schemes and similar style, so why
is it that at the bridge between the two we have something that looks like
neither? I think the for_each syntax I'm referring to is a clean bridge
between the two, because it (logically, if not in code) maps the syntax of
STL iterators to the syntax of MPL iterators in standard algorithm calls.
The paper I referred to gave the most compelling argument for having
precisely the same syntax at the bridge: you can test with the run-time
version (short compile times) and release with the compile-time version
(short execution times): they needed only to switch the object from
std::vector to a compile-time vector, wait for KAI C++ to grind away for
24 hours, and they got 171 times the performance.

> AFAICT it
> doesn't solve the problem that Andrei was pointing at.

You mean the front/pop_front issue?

> It also has at
> least one problem: it is intrusive on sequence types, requiring them
> to have begin()/end() member functions. If this was the only way to
> do it, it would break interoperability with 3rd-party type sequences.
>
> -Dave

That's easy to fix---I was just trying to keep the example small. A few
extra abstractions would be needed:

namespace mpl {
  // Special type that for_each can pick up on
  template<typename Iterator>
  struct iterator
  {
    typedef Iterator type;
  };

  // Stores an MPL sequence defined by an iterator range
  template<typename Begin, typename End>
  struct sequence
  {
    iterator<Begin> begin() const { return iterator<Begin>(); }
    iterator<End> end() const { return iterator<End>(); }
  };

  template<typename Begin, typename End, typename F>
  F for_each(iterator<Begin> first, iterator<End> last, F f)
  {
    // ...
  }
}

Just stick your third-party iterators into sequence<> and you're all set;
I'd expect that mpl::list, mpl::vector, etc. would just derive from
mpl::sequence to reduce the amount of typing in the common case.

        Doug


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