C++ reverse an iterator - c++

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

Related

Can std::iterator check, if the next element exist over that iterator? ( This design is restricted by a HOMEWORK)

I have a template Iterator class that contains std::iterator of container that is specified by template. I did not find any way to check if the next element exist over the iterator, without using container.
There is a control like this;
vector<int> v;
vector<int>::iterator itr;
if(itr== v.end()) { /*...*/}
but I wanted to do this control in my Iterator class and my class is like following...
template <class E, class C= vector<E> >
class Iterator {
public:
/*...*/
bool hasNext()noexcept;
/*...*/
private:
typename C::iterator itr; // is there any problem with this decleration?
};
//implementation of hasNext() function.
template<class E, class C>
bool
Iterator<E,C>::hasNext()noexcept {
return(itr!=end())?true:false; // this line is wrong. How can I fix it?
}
An iterator represents a position within a sequence of items. An iterator knows how to get to the next element in that sequence, but the nature of C++'s iterator model is based on the idea that there exists a "past-the-end" iterator after the end of such a sequence. Such an iterator does not represent a valid item in the sequence; it merely represents the end of the sequence, and iterators can be tested against it.
This construct is useful, as it allows you to talk about sub-ranges of elements within a sequence. For example, if a container has 10 elements, you can pass the begin/end iterators to the std::sort algorithm to sort them. However, you could also sort the first 10 elements by passing the begin iterator and the begin() + 10 iterator to the same function. The sort algorithm will treat the given ending iterator as the "past-the-end" iterator, not an iterator to a valid element.
What you are trying to do is combine two distinct ideas: position and range. Some iteration models do things that way, but that is not the STL-derived model that C++'s standard library is based on.
Now to be fair, there are some cases where position inherently carries range information. stream-based iterators know whether they are at the end of the stream or not, because to function as an iterator, they have to store a reference to the stream they iterate over. And the stream knows whether it is out of data. But overall, a single iterator is not meant to know whether it is at the end of its range or not.

How to make sure the parameters of function template are random access iterator?

I am writing a function with has as parameter, an iterator to any type of data structure.
template<class Iterator>
void Foo(Iterator first, Iterator last) {
...
}
However, due to my algorithm, I must be sure that the iterator is a random access iterator. How can I redefine my function such as only Random Access Iterator can be used as parameter ?
I could use my iterator as a Random Access Iterator and so, the code will not (or may not ?) compile in other case. But I'm not sure that it is the most elegant solution.
Uncompiled code:
static_assert(std::is_same<std::iterator_traits<Iterator>::iterator_category,
std::random_access_iterator_tag>::value,
"Random-access iterators are required" );
The iterator_traits<>::iterator_category gives you what kind of iterator it is. Comparing it to std::random_access_iterator_tag tells you if it's a random access iterator.
Wrapping the whole thing in a static_assert gives you a compile-time error if the condition is not met - along with a nice error message.

STL fill and forward iterator

According to most C++ references, for instance cplusplus.com, forward iterators are not required to be assignable (I mean, deferenced to an lvalue). However, for several STL algorithms that need to write values, for instance std::fill (also std::generate etc.), the specification uses forward iterator:
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val);
while the equivalent behavior requires lvalue dereference:
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
while (first != last) {
*first = val;
++first;
}
}
So, it is actually using a mutable forward iterator with a single pass.
Now the questions are:
(1) Why not make it clear that the forward iterators used in these cases are mutable?
(2) Update: I found the following question to be stupid: I temporarily forgot that output iterators do not need to support equality comparison. The above question remains, anyway.
Why use forward iterators instead of output iterators for std::fill, std::generate etc. while they do not actually need multiple passes? (std::copy only needs output iterators, for instance. What's the rationale?)
From the signature
template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val);
you cannot infer that ForwardIterator is an iterator described in forward iterator. However, if you read the parameter description, you will find that first and last must be
Forward Iterators to the initial and final positions in a sequence of elements that support being assigned a value of type T.
(emphasis by me). So a forward iterator that fulfills nothing more than what is required of a forward iterator is not a valid argument.
It doesn't seem terribly strange to me, given that the specification for fill is that the (dereferenced) iterator be assignable from T. An output iterator won't suffice because it's not comparable to determine the range end, so a forward_iterator with requirements was chosen.
You'll note that fill_n does use output iterators because no iterator comparison is needed to determine the end of the sequence to fill.

iterator successor

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.

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.