I am writing an iterator for a container which is being used in place of a STL container. Currently the STL container is being used in many places with the c++11 foreach syntax eg: for(auto &x: C)
. We have needed to update the code to use a custom class that wraps the STL container:
template< typename Type> class SomeSortedContainer{ std::vector<typename Type> m_data; //we wish to iterate over this //container implementation code }; class SomeSortedContainerIterator{ //iterator code };
How do I get auto to use the correct iterator for the custom container so the code is able to be called in the following way?:
SomeSortedContainer C; for(auto &x : C){ //do something with x... }
In general what is required to ensure that auto uses the correct iterator for a class?
Working of the foreach loop in C++ So basically a for-each loop iterates over the elements of arrays, vectors, or any other data sets. It assigns the value of the current element to the variable iterator declared inside the loop.
The working of foreach loops is to do something for every element rather than doing something n times. There is no foreach loop in C, but both C++ and Java have support for foreach type of loop. In C++, it was introduced in C++ 11 and Java in JDK 1.5. 0 The keyword used for foreach loop is “for” in both C++ and Java.
IntegersType::iterator begin() { return m_data. begin(); } IntegersType::iterator end() { return m_data. end() } private: IntegersType m_data; }; The code above works because all containers in the C++ Standard Library do what we have done with our Integer container: they all implement their iterators as class members.
To be able to use range-based for, your class should provide const_iterator begin() const
and const_iterator end() const
members. You can also overload the global begin
function, but having a member function is better in my opinion. iterator begin()
and const_iterator cbegin() const
are also recommended, but not required. If you simply want to iterate over a single internal container, that's REALLY easy:
template< typename Type> class SomeSortedContainer{ std::vector<Type> m_data; //we wish to iterate over this //container implementation code public: typedef typename std::vector<Type>::iterator iterator; typedef typename std::vector<Type>::const_iterator const_iterator; iterator begin() {return m_data.begin();} const_iterator begin() const {return m_data.begin();} const_iterator cbegin() const {return m_data.cbegin();} iterator end() {return m_data.end();} const_iterator end() const {return m_data.end();} const_iterator cend() const {return m_data.cend();} };
If you want to iterate over anything custom though, you'll probably have to design your own iterators as classes inside your container.
class const_iterator : public std::iterator<random_access_iterator_tag, Type>{ typename std::vector<Type>::iterator m_data; const_iterator(typename std::vector<Type>::iterator data) :m_data(data) {} public: const_iterator() :m_data() {} const_iterator(const const_iterator& rhs) :m_data(rhs.m_data) {} //const iterator implementation code };
For more details on writing an iterator class, see my answer here.
You have two choices:
begin
and end
that can be called like C.begin()
and C.end()
;begin
and end
that can be found using argument-dependent lookup, or in namespace std
, and can be called like begin(C)
and end(C)
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With