I'm interested in the implementation of the reverse iterator with rbegin(), rend() and operator++ of the class string, I can't find it in google, how can I do it? thanks in advance for any help or any link
You could look in the implementation header files. (e.g. /usr/include/c++/4.1.2/string on Linux). This will typically just pull in a load of other headers where the real meat lies, such as bits/basic_string.h.
I don't know where they reside for e.g. VC++, but you can usually just get Intellisense to find it by creating a std::string, selecting it and pressing F12.
There is a basic implementation of reverse_iterator in the STL.
It is templatized by the Iterator to be reverted.
The idea is quite simple, if you look at a range:
[first, second, .... last]
^ ^
begin end
rend rbegin
There is extra-work done, compared to a pure reverse iterator using this implementation, since for each dereference, you need to copy the iterator you hold, decrement it, and then dereference it.
Reverse iteration for bidirectional iterators is implemented in the std::reverse_iterator template.
The implementation of reverse iterators for std::string doesn't take more than:
template <xxx>
class basic_string
{
public:
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin() { return reverse_iterator(this->end()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(this->end()); }
reverse_iterator rend() { return reverse_iterator(this->begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(this->begin()); }
//...
};
(Copied from GCC's implementation.)
Related
EDIT: This question was closed even though none of them talked about reverse iterators, so my question still stands
If you want to implement iterators correctly inside a custom container, in such way that supports STL algorithms and range-based for loops you, must use an API and define some functions and typedefs.
What are the requirements of this API for iterators? and reverse iterators?
I know that for iterator (not reverse_iterator) you need your custom container to have the following and I don't know if there's anything else or this really is what you need: (the <> represent a placeholder, and not a template for exmaple)
Inside the Container Class
typedef <IteratorClass> iterator;
typedef <ConstIteratorClass> const_iterator;
iterator begin ();
const_iterator begin () const;
const_iterator cbegin () const;
iterator end ();
const_iterator end () const;
const_iterator cend () const;
Inside the Iterator Class (and you need a const iterator class as well)
typedef <ValueType> value_type;
typedef <ReferenceType> reference;
typedef <PointerType> pointer;
typedef <DiffType> difference_type;
typedef <IteratorCategory> iterator_category;
Does reverse Iterator require something similar?
In the following image I'm using the same type of iterators which means the same implementation of operator++ so how does the compiler know if it should get the next value or the previous one...?
First, the picture you have contains an error. As you can see here the reverse iterator type of vector is std::reverse_iterator<iterator> which uses the template std::reverse_iterator<T>. So begin and rbegin have not the same return value (and I also do not think they are convertible to each other).
But actually that wouldn't even be a problem, you could implement
struct iter {
bool reverse;
pointer ptr;
iter& operator++() {
if(reverse) --ptr;
else ++ptr;
return *this;
}
};
But type-seperating them is really preferable.
I was under the impression one cant use erase on a const iterator. Check this code.
Why does the below code compile (C++11, gcc)?
long getMax(const bool get_new)
{
long max_val=0;
TO now=getNow();
map<TO, long>& m=get_new?m_new:m_old;
for(auto it=m.cbegin(); it !=m.cend())
{
if(now.compareTime((*it).first)<lookback)
{
max_val=max(max_val,
(*it).second);
++it;
}
else
{
it=m.erase(it);
}
}
return max_val;
}
The map itself is not constant, but my understanding is that the const iterator should make this fail.
The behavior has changed from C++11; std::map::erase takes const_iterator as its parameter.
void erase( iterator pos ); // (until C++11)
iterator erase( const_iterator pos ); // (since C++11)
iterator erase( iterator pos ); // (since C++17)
For std::map::erase, the passed iterator is just used as the position where the element would be deleted, not for modifying the element through it. That means const_iterator would be fine. Before C++11, the support for const_iterator was not very good, but the situation has changed from C++11. You should use const_iterator instead of iterator when possible now.
Positions are independent of the constness of their access. It was (is?) quite common that functions doing a search return const_iterator because they actually do not change the container at all. However, it is desirable to use the obtained position for mutations of the sequences, e.g., to insert() an element at the corresponding position or to erase() the located element. As a result, the container where extended to support use of const_iterator with mutating operations.
It seems the relevant paper is N2350. I'm not sure if this paper is the latest version.
I have some class called Order. For some reason, the following code won't compile while using rbegin(), but it works for begin(). Is there a problem in the way I'm declaring the iterator or perhaps a problem with my pointer reference?
map<double, list<Order*>> m
typedef map<double, list<Order*>>::iterator iter;
iter iterator;
iterator = m.rbegin(); // this only works for m.begin()
Thank you!
rbegin() returns a reverse_iterator, not an iterator.
The types returned from begin() and rbegin() are different:
begin() returns std::map<K, V>::iterator
rbegin() returns std::reverse_iterator<std::map<K, V>::iterator>
I have a class called PointList, which holds a vector of Point * objects as its main data. I want to iterate over the points the same way you would a vector, kind of like this:
for (vector<Point *>::iterator it = point_list->begin(); it != point_list->end(); ++it)
Clearly the begin() and end() functions I write can just return the vector's begin/end functions that they hold, but what is the return type of these functions?
If I have understood the question right, the answer is right in your question. You already use the return value and type of begin and end in your piece of code.
vector<Point *>::iterator it = point_list->begin();
clearly, it holds the return value of begin() and its type is well known:
vector<Point *>::iterator
By the way, a little off-topic - why point_list is pointer to vector, not an object? And second, why it's called list, as it's vector? Use vector, or array, or sequence, but not list, as it could be misleading. list is a STL container, different from vector.
Their return type would be vector<Point *>::iterator.
You should copy the container interface, by providing two iterator types, three begin functions and three end functions. The most obvious iterator types to use are taken straight from the vector:
struct PointList {
typedef std::vector<Point*>::iterator iterator;
typedef std::vector<Point*>::const_iterator const_iterator;
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
iterator end();
const_iterator end() const;
const_iterator cend() const;
};
cbegin() and cend() are new to C++11, they aren't in C++03. The idea is that since they don't have a non-const overload, the user can call them on a non-const container in preference to messing about with a conversion.
Since the underlying storage is in a vector, you might also consider providing (c)rbegin() and (c)rend(). In fact to implement the standard container interface you'd have to, since your iterator type is random-access. If you don't want to do that (perhaps because some future implementation of this class will not necessarily use a vector, but some other container underneath), then there is an argument for wrapping the vector's iterator in a class of your own just as you've wrapped the vector in a class of your own. That's extra work that's only needed if you need to prevent users from relying on properties of the iterator that could disappear in future implementations. You might not care about this in an internal API, more so in a published one.
They are of type vector<Point *>::iterator just like your it object. But why do you want to iterate your data outside of the container object? That would be violation of encapsulation no?