Generic iterator utility functions

C

Carlo Milanesi

Let's say I want to write the following function,

void f(const list<int> &l, const vector<int> &v) {
cout << get_second(l) << '\n';
cout << get_second(v) << '\n';
cout << get_nth(l, 2) << '\n';
cout << get_nth(v, 2) << '\n';
}

that prints the second and third (counting from zero) items of given
list and vector.
For such a purpose I need to write the generic functions (i.e. function
templates) 'get_second' and'get_nth' that, respectively, return the
second and the n-th item of the given collection. Possible
implementations of these two functions are the following ones:

template<typename Coll>
inline typename Coll::value_type get_second(const Coll &coll) {
// return *++(coll.begin()); // Wrong.
// return *(coll.begin() + 1); // Wrong.
typename Coll::const_iterator it = coll.begin();
advance(it, 1);
return *it;
}

template<typename Coll, typename Distance>
inline typename Coll::value_type get_nth(
const Coll &coll, Distance d) {
typename Coll::const_iterator it = coll.begin();
advance(it, d);
return *it;
}

As noted in the code comments, the use of the operator '++' is wrong
(although some compilers accept it) as the function 'begin' shouldn't
return an l-value; and the use of the operator'+' is wrong for
non-random iterators, like those of list. So, the quickest solution I
found was that rather cumbersome code.
But I think that a better solution would be to define the following
function templates:

// Return the successor of the given input iterator.
template<typename InputIterator>
inline InputIterator succ(InputIterator it) {
return ++it;
}

// Return the predecessor of the given bidirectional iterator.
template<typename BidirectionalIterator>
inline BidirectionalIterator pred(BidirectionalIterator it) {
return --it;
}

// Return an input iterator moved from the given input iterator
// by the given distance.
template<typename InputIterator, typename Distance>
inline InputIterator adv(InputIterator it, Distance d) {
advance(it, d);
return it;
}

and then use them in the following function templates:

template<typename Coll>
inline typename Coll::value_type get_second(const Coll &coll) {
return *succ(coll.begin());
}

template<typename Coll, typename Distance>
inline typename Coll::value_type get_nth(const Coll &coll,
Distance d) {
return *adv(coll.begin(), d);
}

Is it a good idea to keep the functions 'succ', 'prec' and 'adv' in my
toolkit of generic utility functions, or are there better solutions?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,522
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top