[C++] function to take both iterator and reverse_iterator

Started by
27 comments, last by coordz 16 years, 1 month ago
I've written a function to operate on a range like this
template <typename T> vector<T> myFunc(
    const typename vector< vector<T> >::const_iterator &beginIter,
    const typename vector< vector<T> >::const_iterator &endIter );
which works fine when passing normal forward iterators. When I try to pass reverse iterators I get an (expected) compile error. How do I define my function to take either forward or reverse iterators? Is there a base class that both forward and reverse iterators are derived from? Or do I need to further template my function to accept the two types of iterators? TIA
Advertisement
You shouldn't care what kind of iterator you get, from a vector or not:
template <typename Iterator>vector<typename Iterator::value_type> myFunc(Iterator begin, Iterator end){   // ...}


This makes your function more general (the whole point of templates), because it can take user defined iterators. You could even template the return type, allowing greater flexibility.
Quote:Original post by coordz
I've written a function to operate on a range like this
template <typename T> vector<T> myFunc(    const typename vector< vector<T> >::const_iterator &beginIter,    const typename vector< vector<T> >::const_iterator &endIter );

rip-off has a good solution for you already, so I am going to go out on a limb and ask why you want to be returning a std::vector? Unless this is a factory function to initialise vectors, it might be better to operate in place, ala std::copy.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I don't want to make the function any more generic than it is as it does not make sense for it to operate on anything other than a vector< vector<> >. To be brief, the function selects a path through a 2D grid of T and returns this path as a vector. I just want to be able to do a forward path and reverse path easily.
You already have your answer:


template <typename T, typename Iter>
vector<T> myFunc(Iter beginIter, Iter endIter);
Quote:Original post by rip-off
You shouldn't care what kind of iterator you get, from a vector or not:
*** Source Snippet Removed ***

This makes your function more general (the whole point of templates), because it can take user defined iterators. You could even template the return type, allowing greater flexibility.


Not all iterators provide the same level of functionality. What if myFunc uses some functionality of a random access iterator for instance which is not supported by a forward iterator? This contradicts your initial goal of making this function general.
Quote:Original post by Ashkan
Not all iterators provide the same level of functionality. What if myFunc uses some functionality of a random access iterator for instance which is not supported by a forward iterator?

If you pass a forward iterator and your function expects a random access iterator, then you will get a compile time error immediately. Because it is a templated function, the compiler will discover immediately that the passed iterator has no random access functionality.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoder
Quote:Original post by Ashkan
Not all iterators provide the same level of functionality. What if myFunc uses some functionality of a random access iterator for instance which is not supported by a forward iterator?

If you pass a forward iterator and your function expects a random access iterator, then you will get a compile time error immediately. Because it is a templated function, the compiler will discover immediately that the passed iterator has no random access functionality.


Exactly my point. Then what's the point of making this function general? Why not pass a random access iterator in the first place?
A lot of functions in the STL only support certain types of iterators, so while this function could be made more generic, it is not necessarily the right approach in all situations.

Reverse iterators have a base() method, which returns the corresponding iterator for the given range. That may be what you need to look into if you want to use the function as-is (though you may have to change the const_iterators to iterators).

Excellent article on this right here (specifically point 3 in your case)
Dr. Dobb's - Three Guidelines for Effective Iterator Usage

Quote:Original post by Ashkan
Not all iterators provide the same level of functionality. What if myFunc uses some functionality of a random access iterator for instance which is not supported by a forward iterator? This contradicts your initial goal of making this function general.


Since the OP didn't specify what the function was to do initially, I went for the most general one. People often over-specify template functions when there is a more general alternative available.

Besides, had the OP used a random access iterator specific construct (such as begin + 5) the compiler would reject an instantiation of the template for non random access iterator types, which is fine.

This topic is closed to new replies.

Advertisement