Boost logo

Boost :

From: Thomas Becker (tmbecker1_at_[hidden])
Date: 2003-03-28 02:48:49


--- Anthony Williams
<anthony.williamsNOSPAM_at_[hidden]> wrote:

> Basically, I think we have two contradictory
> scenarios. IIUC, the situations
> you have encountered are where you have a set of
> values in different
> containers that needed to be combined into a single
> value, in which case it
> makes sense to pass the values as distinct function
> arguments to a functor
> that does the combining.

That's true, that was the scenario that the combining
iterator grew out of, and that has certainly tilted my
perception of the problem in that direction. But when
I conceived of my combining iterator, I *did* think
about the other scenario that you mention:

>
> OTOH, the situations I am thinking of require that
> the tuple of containers is
> really treated as a container of tuples, complete
> with the ability to update
> the source containers by writing to the tuple
> obtained by the dereferencing,
> but maintaining the value semantics when copied.
> This is really hard to do in
> any other way than by having *it return a "magic
> tuple", IMHO, though if you
> can find a way of doing it as a functor that "just
> works" without the user
> having to know too much, I'll concede the point.

Because of my tilted perception, I sort of dismissed
that scenario by saying to myself, ah, shucks, just
write a functional that returns a suitable reference,
and you're good. You are now forcing me to think about
this more carefully, for which I am grateful to you.
Unless I'm missing something, I believe that my
original rough intuition was ok. Given my combining
iterator, it seems very easy to write your tuple
iterator by providing a simple generic
"reference-tuple-making" functional. As always in
these situations, it's a little messy to provide one
functional that will work for all n (n=number of
member iterators), so for simplicity, here's the case
n=2:

template<typename Type1_, typename Type2_>
class FunMakeReferenceTuple_2
{
public:
  typedef boost::tuple<Type1_&, Type2_&> result_type;
  boost::tuple<Type1_&, Type2_&> operator()(
    Type1_& refFirst,
    Type2_& refSecond
    ) const
  {
    return boost::tuple<Type1_&, Type2_&>(
      refFirst,
      refSecond
      );
  }
};

I've tested this in several examples, e.g., I created
two vectors of ints, filled them with values to equal
length, then created a combining_iterator from the two
begin positions and the functional

FunMakeReferenceTuple_2<int, int>

Once I have this combining iterator, I can read and
write both vector elements to my hearts delight. E.g.,

std::swap(it->get<0>(), it->get<1>());

will swap the values at the current position, or,

*it = boost::make_tuple(42, 43);

will assign 42 and 43 to the respective vector
elements.

If you want to, you can easily wrap all this up and
provide a tuple_iterator which internally uses my
combining iterator in conjunction with the
reference-tuple-making functional. I now strongly
believe that that's the way to go. The combining
iterator handles for you everything that has to do
with the parallel-iteration. Via the funcional, you
decide how to process the dereferenced iterators. The
tuple_iterator is the special case (or rather, the
large subclass of cases) where that processing
consists of making a tuple of references. There's
certainly more to think about, like, what about const
tuple iterators, but I believe that the questions and
answers are the same whether you write the tuple
iterator from scratch or use my combining iterator. In
fact, doing it with the combining iterator seems
somehow "intellectually cleaner" to me, because all
the parallel iteration stuff is hidden and out of the
way, so you can focus on the tuple issues.

BTW, in my software, I do have cases where I need to
parallel iterate and write to the current positions,
but in those cases, I always deal with sequences of
possibly different length (think portfolio of assets
with different dates of inception). Now
parallel-iteration is really ugly business. There's
always a bigger can of worms...

Thomas Becker
Zephyr Associates, Inc.
Zephyr Cove, NV
thomas_at_[hidden]

__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com


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