Reputation: 313
To my understanding, iterators are a mechanism for providing an interface for the client to observe/iterate/pass through the contents of, for example, a custom collection, without breaking the information hiding principle. STL containers have iterators of their own, so we can use for ( : )
and for_each
loops on them with no problems.
My question initially was: why inherit from std::iterator
? What additional functionality does it provide, in contrast to the following example:
SimpleArray.h
class SimpleArray
{
int *arr;
int n;
public:
explicit SimpleArray(int = 1);
~SimpleArray();
friend ostream& operator<<(ostream&, const SimpleArray&);
friend istream& operator>>(istream&, SimpleArray&);
// encapsulated "iterator"
class Observer
{
int *p;
public:
Observer(int *value = nullptr) : p(value) {}
Observer& operator++() { p++; return *this; }
Observer operator++(int) { int *temp = p; p++; return Observer(temp); }
bool operator==(Observer other) const { return p == other.p; }
bool operator!=(Observer other) const { return p != other.p; }
int& operator*() const { return *p; }
};
Observer begin() { return Observer(arr); }
Observer end() { return Observer(arr + n - 1); }
};
Source.cpp
int main()
{
SimpleArray array(5);
cin >> array;
for (int item : array)
{
cout << item << " ";
}
cin.ignore();
cin.get();
}
Input
1 2 3 4 5
begin()
and end()
functions are public and the Observer
encapsulates all the necessary operators for the loop to function. The code compiled.
Output
1 2 3 4 5
After trying the same with std::for_each
std::for_each(array.begin(), array.end(), [](int item) { cout << item << " "; });
I got some compiler errors:
C2062: type 'unknown-type' unexpected Observer
C2938: '_Iter_cat_t<SimpleArray::Observer>' : Failed to specialize alias template
C2794: 'iterator_category': is not a member of any direct or indirect base class of 'std::iterator_traits<_InIt>'
After reading about for_each, I found out its type parameters must meet some requirements, in short - to be Iterators.
My question now is: why is this function (and many others for certain) designed in a way that enforces this criteria, if it is fairly easy to create a regular class that provides the iterating functionality?
Upvotes: 2
Views: 1235
Reputation: 1243
The only thing std::iterator
provides are the member types iterator_category
, value_type
, difference_type
, pointer
, and reference
, which are defined from the template parameters you provide. It doesn't have any other members. You can just define these member types yourself.
The real answer is that you don't need to inherit from std::iterator
at all and it doesn't give you any real advantage. As far as C++ is concerned, if it looks like an iterator, it is an iterator. You just need to make sure your iterator type follows the concepts outlined here: https://en.cppreference.com/w/cpp/named_req/Iterator
std::iterator
was deprecated in C++17 because of how relatively useless it is.
Upvotes: 10