0lt
0lt

Reputation: 313

Why (must one) inherit from std::iterator?

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

Answers (1)

Jordan M
Jordan M

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

Related Questions