Defining iterator of my own container

前端 未结 3 1964
时光说笑
时光说笑 2021-01-02 02:47

I am confused with some concepts about defining my own iterator:

From this: http://www.cs.northwestern.edu/~riesbeck/programming/c++/stl-iterator-define.html, which

相关标签:
3条回答
  • 2021-01-02 03:18

    Although @templattypedef's answer is accurate, perhaps I can clarify the situation a little bit.

    An iterator is typically defined as a nested class inside the container. std::iterator is typically used as a base class to make it easier for you to define your iterator class. You never really have to use std::iterator -- it's just there to make the job a bit easier and (especially) reduce the amount of code you need to type. In fact, std::iterator is officially deprecated, so using it is discouraged. It might someday be removed from the standard (though I don't know of any concrete date when it's likely to be removed).

    Oh, and for reasons that have no bearing on the question at hand, it's sometimes preferable for an iterator to be defined outside the container class being iterated. When the iterator class definition is nested in the container definition, the iterator depends on all the template parameters of the surrounding class. That's rarely necessary or desirable though. For example, two vectors with different allocators can still normally have the same iterator type--changing the allocator doesn't change iteration.

    0 讨论(0)
  • 2021-01-02 03:26

    Although using std::iterator may help with typedefs, it certainly doesn't help with the actual implementation.

    The Boost.Iterator library has lots of good things for this, and I'll suggest to read about the boost::iterator_adaptor which greatly reduce the amount of code you need to type to define a new iterator on top of an old one.

    0 讨论(0)
  • 2021-01-02 03:34

    The C++ specification on what exactly an STL container is mandates that any STL container type have several different fields available. Some, like begin() and end(), are functions, while others, like iterator, are types. These restrictions also apply to iterators. This allows C++ template functions to introspect on their types of their arguments to look up more properties. For example, all STL iterator types must define an iterator_category field containing a type encoding their capabilities. This way, the STL algorithms can have different implementations of different functions based on the power of the iterators they accept. A class example is the distance function, which takes two iterators and returns the number of spaces between them. If the input is a lowly ForwardIterator or BidirectionalIterator this works by marching the iterators forward and counting how many steps were took, which runs in O(n). If the input is a RandomAccessIterator, then the iterators can just be subtracted to get the result in O(1).

    Prior to C++17, the recommendation was to include the <iterator> header and inherit from std::iterator to automatically generate the necessary nested types you’d need (reference, pointer, etc.). That type is now deprecated, and so you’ll need to manually either add typedefs or specialize std::iterator_traits to export this information.

    As for what operators you need to overload, at a bare minimum you need to get ++ (prefix and postfix), ==, !=, * (pointer dereference), and -> defined. All iterator types support this. For bidirectional iterators or higher, you should also have -- defined (prefix and postfix). Finally, for random-access iterators, you should support [], +, +=, - (back up many steps and subtract two iterators), -=, <, >, <=, and >=.

    Hope this helps!

    0 讨论(0)
提交回复
热议问题