$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Lewis Hyatt (lhyatt_at_[hidden])
Date: 2005-10-12 18:39:54
Hi All,
        I am in the middle of writing a large body of numerical code for data 
analysis and have found the boost library very useful for a number of 
things. I do a lot of work with std::map and with containers of 
std::pair objects, and one thing I've always felt annoyed with is the 
difficulty of interfacing a value_type of std::pair with the STL 
algorithms. Frequently, for instance, it is nice to represent data as a 
std::list< std::pair<double,double> > and then to be able to work with 
the first and second coordinates independently and pass them to 
std::accumulate() or whatever. The SGI extensions select1st() and 
select2nd() are somewhat useful but also non-standard, and they 
frequently require memory-wasting buffers to store only the first or 
second elements.
I have a relatively simple system for solving this problem and it 
strikes me as the kind of quick thing that might be worth including in 
boost. The idea is to define a template class,
template<typename Iterator> class first_iterator_t {
        Iterator pair_iter;
public:
        first_iterator_t(Iterator const&);
        /*...*/
};
which overloads operator*() and operator->() to access the element named 
"first" of the object returned by Iterator::operator*(). (With something 
analagous for second_iterator_t.) A function named first_iterator() 
provides a convenient creation function a-la std::make_pair().
That's it for the most part, the class only needs to provide the 
required iterator interface which mostly consists of just calls to 
Iterator::operator functions. There is also the need to define the 
appropriate iterator_traits typedefs. There is a small issue of deducing 
whether the iterator needs to be a const iterator or not, which can be 
solved with partial specialization of a second template class containing 
nested typedefs.
The end result is that something like this is now conveniently available:
map<int, double> m;
m[1] = 0.1; m[2]=0.2; m[5]=0.5;
//prints: 1	2	5
copy(first_iterator(m.begin()), first_iterator(m.end()), 
ostream_iterator<int>(cout, "\t"));
//prints: 0.1	0.2	0.5
copy(second_iterator(m.begin()), second_iterator(m.end()), 
ostream_iterator<double>(cout, "\t"));
I don't see a way to do this otherwise without resorting to something 
like select1st(), and that also requires the use of std::transform(), 
which I find distasteful since the required operation is really just a 
simple copy.
So anyway do you think this is useful enough to possibly include in 
boost somewhere, or is it too trivial? I have what I believe to be 
correct code, which could be made boost-ready with little effort.
Thanks for your advice!
-Lewis