By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,159 Members | 882 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,159 IT Pros & Developers. It's quick & easy.

Generic iterator utility functions

P: n/a
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?

--
Carlo Milanesi
http://digilander.libero.it/carlmila
Jul 19 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.