4

I thought there are no differences, but I'm confused because while reading the draft of C++ standard, 24.5.1.1, reverse_iterator, I found that the reverse_iterator is inherited from iterator and also has explicit typedefs difference_type, pointer, and reference.

template <class Iterator>
class reverse_iterator : public
    iterator<typename iterator_traits<Iterator>::iterator_category,
             typename iterator_traits<Iterator>::value_type,
             typename iterator_traits<Iterator>::difference_type,
             typename iterator_traits<Iterator>::pointer,
             typename iterator_traits<Iterator>::reference> {
    public:
        typedef Iterator iterator_type;
        typedef typename iterator_traits<Iterator>::difference_type difference_type;
        typedef typename iterator_traits<Iterator>::reference reference;
        typedef typename iterator_traits<Iterator>::pointer pointer;

Why is it written like this?

kjh6b6a68
  • 499
  • 2
  • 8

1 Answers1

1

This has been in the standard since C++98, so it is going to be a bit hard to find some context for how it came about.

Here is a just a guess:

They may have wanted to inherit the iterator from std::iterator as a matter of policy to inherit all iterators from it (not sure about that).

But if you were to simply copy the exposition as is and try to use it as a definition of the interface of reverse_iterator, then these typedefs are required.

If you removed e.g. the typedef for difference_type, then you couldn't use it later in e.g. the declaration

reverse_iterator operator+ (difference_type n) const;

That is because iterator<...> is a dependent base class of the class, meaning the actual type of the base depends on a template parameter. It has a difference_type member, but members of dependent base classes cannot be named directly, since the compile can't know yet at the point of the template's definition what members the dependent base class has. They must be qualified, i.e. for a type like here you need to write typename iterator_traits<Iterator>::difference_type to access it.

They probably didn't want to repeat that long thing every time they mention difference_type but still keep it proper C++ code. So they simply introduce the typedef for convenience.

From the outside when referring to a reverse_iterator<...>::difference_type the typedef doesn't change anything. In terms of the interface, there isn't really any practical difference between inheriting from iterator and declaring the type aliases manually. The only difference is that you can test whether the iterator is inherited from std::iterator. And as discussed in the comments under the question, std::iterator has been deprecated in C++17 anyway and shouldn't be used anymore at all.

That would also explain why only the members that are referred to later are typedef'ed and not e.g. iterator_category and value_category.

user17732522
  • 53,019
  • 2
  • 56
  • 105