iterator successor - c++

I want to initialize an iterator (of arbitrary kind) with the successor of another iterator (of the same kind). The following code works with random access iterators, but it fails with forward or bidirectional iterators:
Iterator i = j + 1;
A simple workaround is:
Iterator i = j;
++i;
But that does not work as the init-stament of a for loop. I could use a function template like the following:
template <typename Iterator>
Iterator succ(Iterator it)
{
return ++it;
}
and then use it like this:
Iterator i = succ(j);
Is there anything like that in the STL or Boost, or is there an even better solution I am not aware of?

I think you're looking for next in Boost.Utility. It also has prior for obtaining an iterator to a previous element.
Update:
C++11 introduced std::next and std::prev.

Related

C++ reverse an iterator

Is it possible to reverse an iterator in C++?
For instance, a lot of algorithms are designed on the principle that you pass the beginning and ending iterators:
template <typename T>
void func( Iterator begin, Iterator end ){
...
}
Now suppose that internally, I need to iterate forward and backward over the container:
template <typename T>
void func( Iterator begin, Iterator end ){
// Iterate forward
...
// Iterate backward
...
}
I COULD certainly pass a negative value to std::advance. But I am wondering if it would instead be possible to just convert the iterators to reverse iterators. Is that possible?
You can just call std::make_reverse_iterator on the arguments to get a reverse view of the range. The cpp reference page has a demo. That is of course assuming reversal is possible.
No that is not possible in full generality. For example, consider a singly-linked list where you can only iterate in one direction (i.e. it is Forward iterable but not Bidirectional iterable).
A solution in your case would be for the caller of the function to pass reverse iterators.
Reference: https://en.cppreference.com/w/cpp/experimental/ranges#Iterators

Is it safe in C++ to subtract from container.end()?

That is, providing that container is not empty, can I safely do this:
std::vector<int> container;
container.push_back( 0xFACE8D );
auto last = container.end() - 1;
and this:
EDIT: replaced -1 with -- here:
std::list<int> container;
container.insert( 0xFACE8D );
auto last = container.end();
--last;
and again for arbitrary non-empty container?
EDIT: let me clarify the question.
Sometimes perfectly legal code behaves incorrectly. The question is: assuming that the above code compiles, is it safe to do something like that?
It should be safe for ordinary C-style arrays because the corresponding iterators are just pointers. But is it safe for more complicated containers?
Suppose that one implements list with iterators like this one:
class MyListIterator {
MyListIterator *prev, *next;
MyListIterator * operator--() { return prev; }
...
};
class MyList {
MyListIterator *end() { return NULL; }
...
};
Then an attempt to decrement container::end(), despite being perfectly legal syntactically, would cause a segfault.
I hope, though, that stl containers are much smarter than that. Thus the question on the guarantees on the above stl::list code behavior, if any.
std::vector returns random-access iterators, so yes, this is safe with vector.
std::list returns bidirectional iterators. They can be incremented (++) and decremented (--), but don't allow for arbitrary arithmetic (+, -) or relative comparisons (>, <). It's not safe with list.
You can use std::advance on bidirectional iterators to advance or rewind arbitrary amounts. In C++11 you can use std::prev in place of iter - 1.
The C++ standard says that std::vector<T>::iterator is random access iterator pointing to the past-the-end element. So your can safely use - and + operators.
Unlike std::vector, std::list<T>::iterator is bi-directional iterator that support only -- and ++ operators.

Overloading operator < for non-random iterators

I wanted to know if we could overload the operator < for non-random iterators like those of std::list, std::map, etc. Say for example if I overload it for std::list then :
bool operator < (std::list<T>::iterator &i1, std::list<T>::iterator &i2)
{
return (&*i1 < &*i2);
}
My main purpose is to do an iteration like this :
for (auto i = l.begin(); i < l.end(); ++i) // possible for std::vector, std::deque, etc
// I want to do this instead of i != l.end()
But the compiler says :
[Error] declaration of operator< as non-function
Anyone has any solutions ?
It just doesn't make sense to do a less than comparision on iterators that do not provide it. Using your example with a std::list the nodes of the list could be anywhere in memory. Trying to compare the addresses of the nodes is pointless as the first node could have a higher address than all of the other nodes. If that is the case then you would never loop through the list. The only way this works is to have a sentinel node(end) and every iteration check to see if you are not equal to it. By doing this you know you have not reached the end and you can continue. Once you compare equal to the end then you know you have reached end of the list.
You are working in the wrong direction. Non-random-access iterator does not support operation < for a reason. Basically, it is not possible to implement operation < in a rational way for non-random-access iterators. In your case, you should write:
for (auto i = l.begin(); i != l.end(); ++i)
instead. Or, if C++11 is supported, consider the possibility of using a range-based for loop.
As to your code:
bool operator < (std::list<T>::iterator &i1, std::list<T>::iterator &i2)
{
return (&*i1 < &*i2);
}
It is not OK in two ways.
std::list<T>::iterator is a dependent name. You need to qualify it with typename.
Template argument for T cannot be deduced from the iterator type. It must be specified explicitly.
So, how to solve the second issue? Well, I don't think it is possible. The actual type of the iterator is not specified in the standard, and is considered an implementation detail.
I'd suggest using std::remove_if (and then erase of course), this is much clearer what you are doing and should also be efficient. If you can use C++11 then the predicate can be a lambda and it's really compact.

Why doesn't Boost.Range is_sorted require forward iterators?

The C++11 algorithms std::is_sorted and std::is_sorted_until both require ForwardIterators. However, the Boost.Range version boost::is_sorted only requires SinglePassRanges which corresponds to InputIterators. In particular, it delegates to an an iterator-based implementation like this:
template<class Iterator, class Comp>
inline Iterator is_sorted_until (Iterator first, Iterator last, Comp c) {
if (first == last)
return last;
Iterator it = first; ++it;
for (; it != last; first = it, ++it)
if (c(*it, *first))
return it;
return it;
}
Here we see a *first iterator dereference that happens after the ++it iterator increment. This means that Iterator should have ForwardIterator as its required category. Why? Because the Standard says so in
24.2.3 Input iterators [input.iterators]/p2 (see table 107 with the line about ++r)
post: any copies of the previous value of r are no longer required
either to be dereferenceable or to be in the domain of ==.
Note: this is not intended to be "a proof by single example", but it seems that any comparison based algorithm (e.g. adjacent_find) would necessarily require forward iterators in order to be able to make a comparison between two iterators.
Question: why doesn't the Boost.Range version of is_sorted require the stronger concept of ForwardRange (and ForwardIterator for its low-level routines) that is required by std::is_sorted? Is it a bug in Boost.Range?
It looks like the iterator versions in boost.algorithm correctly require ForwardIterators. And believe it or not, there are also range-based versions in boost.algorithm. Code duplication at its best. The documentation is lagging behind the source according to Ticket #9367, Changeset #86741 corrects the rest of the documentation to state that all flavors of the sort-checking algorithms require ForwardIterators.
I would prefer the implementations in <boost/algorithm/cxx11/is_sorted.hpp> over those in <boost/range/algorithm_ext/is_sorted.hpp> which seem to be bit-rotting since 2010.
EDIT: Digging around, it appears that the Boost.Range implementations did require ForwardIterator, but this commit broke them in 2010?!?.

Is there a C++ equivalent to Java's Collection interface for STL container classes?

I would like to pass arbitrary container as an argument of function and iterate over it (no erasing nor pushing elements). Unfortunately it looks like there is no standard way of doing this.
First solution which comes to my mind is an interface (let's call it CollectionInterface) implemented by classes that will wrap STL containers. so the function declaration would look like:
f(const CollectionInterface * collection);
Or, I was thinking about method template, which has an advantage that it keeps binding at compilation time:
template <class CONTAINER> void f(const CONTAINER & collection);
Which way do you think is better?
ForwardIterator? This is a type of InputIterator (or OutputIterator) that also allows multi-pass algorithms (incrementing it does not invalidate prior values).
Iterators (which are quite different from Java iterators) are the central thread unifying C++ collections. For examples of algorithms working on them (and associated iterator type requirements), you can start with <algorithm>. In particular, search provides an example of using ForwardIterator. It finds the first occurrence within the range [first1, last1] of the sequence defined by the range [first2, last2). These are all objects meeting the requirements of ForwardIterator.
You can also write methods that accept the entire container instead of a reference if that's the way you want to handle things. Iterators into standard library containers are all provided via the member functions begin() and end(), or in some cases rbegin() and rend() for iterating backwards. The way templates work, you don't have to create an actual interface type that objects derive from; the requirements are instead inferred by the object is used.
template<typename Container> void Function(const Container& c) {
for(typename Container::const_iterator i = c.begin(), end = c.end(); i != end; ++i)
//do something
}
Passing iterators provide more flexibility when using the functions, particularly in that not all iterators come from containers with explicit begin() and end() functions, and you can provide whatever explicit subrange you want. But sometimes this method is appropriate.
I would like to pass arbitrary container as an argument of function and iterate over it (no erasing nor pushing elements).
Pass iterators. Here is an example for implementation and use:
template <typename Iter>
void function(Iter begin, Iter end)
{
for (Iter it = begin; it != end; ++it)
{
std::cout << *it << std::endl;
}
}
int main()
{
std::string array[] = {"hello", "array", "world"};
function(array, array + 3);
std::vector<std::string> vec = {"hello", "vector", "world"};
function(vec.begin(), vec.end());
}
Note that in many cases, you don't actually need to write the function, but you can compose it using the library facilities instead and then simply apply std::for_each on that. Or even better, use a preexisting algorithm like std::accumulate or std::find_if.