$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.