Wrap the STL vector and change the behavior of its iterator

There is a code like this:

#include <iostream> #include <vector> template <class T> class A{ public: class iterator : public std::vector<T>::iterator{ public: T& operator*(){ ?? } }; iterator begin(){ return v.begin(); // error } iterator end(){ return v.end(); // error } void add(const T& elem){ v.push_back(elem); } private: std::vector<T> v; }; int main() { A<int> a; a.add(2); a.add(4); for(A<int>::iterator it = a.begin(); it != a.end(); ++it){ std::cout << *it << std::endl; } return 0; } 

This is a wrapper for std::vector with my extra features. I would like to use the std::vector iterator, however I only want to change the operator* behavior for the iterator:

 T& operator*(){ // do some additional function // normal behavior, return value of some element in vector ?? } 

How can I use std::vector and its iterator with a modification of only operator* ? I would also like to wrap functions like begin() and end() for an iterator, how do I wrap them correctly?

EDIT:

Using the answer tips in this section, I managed to solve my problem as follows:

 #include <iostream> #include <vector> template <class T> class A { public: class iterator : public std::vector<T>::iterator { public: iterator(typename std::vector<T>::iterator c) : std::vector<T>::iterator(c) { } T& operator*() { std::cout << "Im overloaded operator*\n"; return std::vector<T>::iterator::operator *(); } }; iterator begin() { return iterator(v.begin()); } iterator end() { return iterator(v.end()); } void add(const T& elem) { v.push_back(elem); } private: std::vector<T> v; }; int main() { A<int> a; a.add(2); a.add(4); for (A<int>::iterator it = a.begin(); it != a.end() ; ++it) { std::cout << *it << std::endl; } return 0; } 

Perhaps this will be useful for someone.

+6
source share
4 answers

Stdlib wrap iterators are best suited for iterator adapters. This task is far from trivial, and Boost.Iterator library exists to simplify the task. Perhaps one of the provided iterators is already solving your problem.

If you are going to write it yourself (I really do not recommend doing this), you must implement your own iterator and create it from vector::iterator , and then overload all the required operators that meet the requirements of the concept that your new iterator models. Also inherit from std::iterator to make traits work. Remember to have a const option. This book has a chapter on developing your own iterators. Also get a copy of the standard (C ++ 03 or C ++ 11, it doesn’t matter here). You will need it.

+3
source

Unfortunately, the only way to do this is to write a complete wrapper for std::vector and its type iterator. This is a lot of work.

+1
source

One does not inherit from std::vector<T>::iterator , since it does not have to be a class. In some implementations, this is just a typedef for T* , and cannot be inherited from a pointer. Also, you should not inherit from standard containers, since they lack a virtual destructor; the possibility is to inherit a private or protected and make all characters and functions visible with typedef and using . In the end, you will have to rewrite the entire vector and its iterators that redirect the calls to the base implementation.

+1
source

I think the answer here is most likely that you should not change the behavior of the * operator for the iterator. Operator overloading should be performed only in cases where it is so intuitive that anyone who reads code that uses the operator automatically knows what is happening. An example of this would be if you had a matrix class and an overloaded + operator. When someone sees that you add two matrix objects together, they can easily find out what is happening.

When dereferencing an iterator, however, there is no intuitive idea of ​​what additional side effects will be for your class.

-1
source

Source: https://habr.com/ru/post/899621/


All Articles