5

Given the following class:

template<class T>
class A {
    vector<T> arr;
public:
    A(int size);
    A(vector<T> arr);
    int size() const;
    A& operator=(const A& p);

    template<class S>
    friend ostream& operator<<(ostream& os, const A<S>& p);

    template<class S>
    friend bool operator==(const A<S>& p1, const A<S>& p2);   
};

How can I define iterator and const_iterator for my class? (I want to uses the iterators of the vectors instead to implement class iterator and class const_iterator)..


I want (for example) to support in something like that:

A a(5);  
for(A<int>::iterator it = a.begin() ; it != a.end() ; it++) { /* .. */ }
Software_t
  • 576
  • 1
  • 4
  • 13
  • Possible duplicate of [How to make my custom type to work with "range-based for loops"?](https://stackoverflow.com/questions/8164567/how-to-make-my-custom-type-to-work-with-range-based-for-loops) – Olivier Sohn Jul 03 '18 at 08:07
  • If you need too many base class methods to be exposed by derived class, it indicates that your derived one is more likely IS-A than HAS-A. But publicly deriving from standard containers is not recommended and is needed in very rare cases. Thus it makes sense to try to revise your class design at first. What additional compared to vector functionality do you want from your class A? – wtom Jul 03 '18 at 08:28

2 Answers2

5

You can simply do this, in C++11:

template<class T>
class A {
    vector<T> arr;
public: 

    using iterator = typename vector<T>::iterator;
    using const_iterator = typename vector<T>::const_iterator;

    const_iterator begin() const { return arr.begin(); }
    iterator       begin()       { return arr.begin(); }
    const_iterator end() const { return arr.end(); }
    iterator       end()       { return arr.end(); }
};

or in C++14:

template<class T>
class A {
    vector<T> arr;
public:
    using iterator = typename vector<T>::iterator;
    using const_iterator = typename vector<T>::const_iterator;

    auto begin() const { return arr.begin(); }
    auto begin()       { return arr.begin(); }
    auto end() const { return arr.end(); }
    auto end()       { return arr.end(); }
};

Then you can both support iterator-based iteration:

A<int> a(5);  
for(A<int>::iterator it = a.begin() ; it != a.end() ; it++) { /* .. */ 
}

And ranged-based for loop:

A a(5);  
for(auto v : a) { /* .. */ 
}

Further explanations on how to support range-based for loop are available here : How to make my custom type to work with "range-based for loops"?

(thanks @JohnML for the edit suggestion to make the answer c++11 compliant!)

Olivier Sohn
  • 1,292
  • 8
  • 18
1

Simply typedef the vector's existing iterator types into your own class:

template<class T>
class A {
    ...
public:
    typedef vector<T>::iterator iterator;
    typedef vector<T>::const_iterator const_iterator;
    ...
};

Or

template<class T>
class A {
    ...
public:
    using iterator = typename vector<T>::iterator;
    using const_iterator = typename vector<T>::const_iterator;
    ...
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    Missing `typename` keywords. (Yes, they're required even though an alias declaration can only be a type.) – aschepler Jul 03 '18 at 13:44