Boost logo

Boost :

From: Anthony Williams (anthony.williamsNOSPAM_at_[hidden])
Date: 2003-03-26 06:19:50


Thomas Becker <tmbecker1_at_[hidden]> writes:

> > Anthony Williams wrote:
> > The particular example I cited in the
> > article is where a colleague
> > had a pair of vectors which were the x and y values
> > respectively for a
> > graph. They were supplied as two vectors, and the
> > graph drawing code required
> > them as two vectors, yet the analysis code in the
> > middle required a sequence
> > of (x,y) pairs
>
> I have to admit this very example has convinced me
> that my original approach is right. Suppose we were to
> write, as you suggest, an iterator adaptor that holds
> a tuple of iterators and, upon dereferencing, returns
> a tuple made from the dereferenced iterators. What
> would we have done for the person in your example?
> Nothing. He needs a *pair*, not a tuple. The big
> picture is: we want an iterator that parallel-iterates
> through several sequences, and upon dereferencing,
> applies some user-defined (via a functional)
> prossesing to the dereferenced iterators. If the
> desired result is a pair, supply a functional that
> makes a pair from its arguments. In my applications, I
> want a number that is calculated from the dereferenced
> iterators, so I supply something like std::divides. If
> the desired result is a tuple made from the
> dereferenced iterators, no problem, supply a
> functional that makes a tuple from its arguments. If
> we used your approach, we would give this one special
> type of processing, where a tuple is made from the
> dereferenced iterators, a very special and prominent
> place in the design. Why? It's just one of infinitely
> many things that someone might want to do.
> (Ironically, it's the one for which we have not seen a
> real-life need.) My general approach covers it with no
> fuss and no overhead. One simple iterator adaptor that
> does it all. We get everything that we would get in
> your approach, and it's simpler and more
> user-friendly. Unless I'm missing something...

A pair is just a special case of a tuple, and a std::pair can be trivially
created from a tuple if really necessary, so that's just a distraction. If my
colleague had had a z axis on his graph we would have needed a triple.

It strikes me that if you dereference n iterators, you have n values, and the
most natural way to store them is a tuple. Doing anything other than returning
this tuple seems to me just complicating the usage.

How do you write the following with your combining iterator? (TupleIt is a
supposed generalisation of my PairIt which returns a tuple rather than a pair)

std::vector<T1> first;
std::vector<T2> second;
std::vector<T3> third;

typedef TupleIt<std::vector<T1>::iterator,
                std::vector<T2>::iterator,
                std::vector<T3>::iterator
>::value_type TupleType;

// could make it a functor with a templated operator() to remove the
// dependency on the specifics of TupleType
bool myCompareFunc(const TupleType& lhs,const TupleType& rhs)
{
    return lhs.get<0>() < rhs.get<0>();
}

std::sort(makeTupleIterator(first.begin(),second.begin(),third.begin()),
          makeTupleIterator(first.end(),second.end(),third.end()),
          myCompareFunc);

Anthony

-- 
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.

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