Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2002-06-26 09:09:04


On Tuesday 25 June 2002 10:48 pm, Andrei Alexandrescu wrote:
> STL does reduce the amount of code you write quite drastically, and it
> would be hard to convince me otherwise because I know that from direct and
> extensive experience.

I'm not referring to STL as a whole, but specifically to the replacement of
hand-coded 'for' loops with STL algorithm invocations. I've found that often
the use of an STL algorithm ends up in more lines of code because one often
needs to create a separate function object to pass to the algorithm, whereas
it would otherwise be written inline. Here's a simplified case that I ran
across a few days ago:

// -----------Hand-coded everything-------------
for (LocationIterator loc = locations.begin(); loc != locations.end(); ++loc)
{
  ValueIterator val = loc->begin();
  Value init = *val++;
  for(; val != loc->end(); ++val)
    init = merge(init, *val);
  loc->merged = init;
}

// ----------STLize inner accumulation---------
for (LocationIterator loc = locations.begin(); loc != locations.end(); ++loc)
{
  ValueIterator val = loc->begin();
  Value init = *val++;
  loc->merged = accumulate(val, loc->end(), init, &merge);
}

// --------------STLize outer loop-------------
struct Merge {
  typedef void result_type;
  void operator()(Location& loc) const
  {
    ValueIterator val = loc.begin();
    Value init = *val++;
    loc.merged = accumulate(val, loc.end(), init, &merge);
  }
};

for_each(locations.begin(), locations.end(), Merge());

In this particular example, there was a 2-line savings when we STLize the
inner accumulation, but if we then STLize the outer loop we need to create
another function object to perform the operations in the loop body (Lambda
library could probably avoid this, but the result expression would be quite
ugly). The result is that the fully STLized version is 10 lines: 2 more lines
than the original version, and 4 more lines than the hybrid with only the
inner loop STLized.

This result is not atypical when writing a nested loop, and I've come across
it quite a few times. Anything but a trivial nested loop tends to require the
introduction of a new function object. Not that I'm complaining -- I find the
last version most preferable (indeed, that's a slightly simplified version of
what I wrote a few days ago), because it separates the complexity nicely: the
for_each line obviously says 'we're merging values at each location'. Want to
know how the merge works? Look up the Merge function object to see how
merging is done.

> But why compare mpl with stl instead of concretely
> discussing on mpl as it stands.

Because the arguments are the same. The reasons for using mpl::for_each or
mpl::accumulate are the same as the reasons for using std::for_each or
std::accumulate. You're citing one pitfall of using MPL -- more lines of code
-- and I'm trying to show that the same pitfall occurs in STL, but the C++
community still agrees that the use of STL algorithm invocations is preferred
to hand-coded loops.

> Because to me it looks like variant.hpp, as
> a sample usage of mpl, is not quite a compelling argument in mpl's favor.
> I'm not sure, but it might be the case that variant's code would benefit in
> terms of length, simplicity, understandability, and compilation times, if
> it would be written without mpl.
>
>
> Andrei

We'll see. Using MPL's placeholders there are a few areas where the variant
code size could be reduced (for instance, there should be no need for
details::add_const or details::max_size)

        Doug


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