This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.

### 2438. `std::iterator` inheritance shouldn't be mandated

Section: 99 [depr.iterator.basic] Status: C++17 Submitter: Stephan T. Lavavej Opened: 2014-10-01 Last modified: 2017-07-30

Priority: 3

View all issues with C++17 status.

Discussion:

For LWG convenience, nine STL iterators are depicted as deriving from `std::iterator` to get their `iterator_category`/etc. typedefs. Unfortunately (and unintentionally), this also mandates the inheritance, which is observable (not just through `is_base_of`, but also overload resolution). This is unfortunate because it confuses users, who can be misled into thinking that their own iterators must derive from `std::iterator`, or that overloading functions to take `std::iterator` is somehow meaningful. This is also unintentional because the STL's most important iterators, the container iterators, aren't required to derive from `std::iterator`. (Some are even allowed to be raw pointers.) Finally, this unnecessarily constrains implementers, who may not want to derive from `std::iterator`. (For example, to simplify debugger views.)

We could add wording to 99 [iterator.basic] saying that any depicted inheritance is for exposition only, but that wouldn't really solve reader confusion. Replacing the depicted inheritance with direct typedefs will prevent confusion. Note that implementers won't be required to change their code — they are free to continue deriving from `std::iterator` if they want.

(Editorial note: The order of the typedefs follows the order of `std::iterator`'s template parameters.)

[Urbana 2014-11-07: Move to Ready]

Proposed resolution:

This wording is relative to N3936.

1. Change [storage.iterator], class template `raw_storage_iterator` synopsis, as depicted:

   >     template <class OutputIterator, class T>
   >     class raw_storage_iterator
   >       : public iterator<output_iterator_tag,void,void,void,void> {
   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;

   >       explicit raw_storage_iterator(OutputIterator x);
   >       […]
   >     };

2. Change 23.5.1.2 [reverse.iterator], class template `reverse_iterator` synopsis, as depicted (editorial note: this reorders "`reference`, `pointer`" to "`pointer`, `reference`" and aligns whitespace):

   >     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;
   >       typedef Iterator                                              iterator_type;
   >       typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
   >       typedef typename iterator_traits<Iterator>::value_type        value_type;
   >       typedef typename iterator_traits<Iterator>::difference_type   difference_type;
   >       typedef typename iterator_traits<Iterator>::pointer           pointer;
   >       typedef typename iterator_traits<Iterator>::reference         reference;

   >       reverse_iterator();
   >       […]
   >     };

3. Change 23.5.2.2 [back.insert.iterator], class template `back_insert_iterator` synopsis, as depicted:

   >     template <class Container>
   >     class back_insert_iterator :
   >       public iterator<output_iterator_tag,void,void,void,void> {
   >     protected:
   >       Container* container;

   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;
   >       typedef Container container_type;
   >       explicit back_insert_iterator(Container& x);
   >       […]
   >     };

4. Change 23.5.2.3 [front.insert.iterator], class template `front_insert_iterator` synopsis, as depicted:

   >     template <class Container>
   >     class front_insert_iterator :
   >       public iterator<output_iterator_tag,void,void,void,void> {
   >     protected:
   >       Container* container;

   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;
   >       typedef Container container_type;
   >       explicit front_insert_iterator(Container& x);
   >       […]
   >     };

5. Change 23.5.2.4 [insert.iterator], class template `insert_iterator` synopsis, as depicted:

   >     template <class Container>
   >     class insert_iterator :
   >       public iterator<output_iterator_tag,void,void,void,void> {
   >     protected:
   >       Container* container;
   >       typename Container::iterator iter;

   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;
   >       typedef Container container_type;
   >       insert_iterator(Container& x, typename Container::iterator i);
   >       […]
   >     };

6. Change 23.6.2 [istream.iterator], class template `istream_iterator` synopsis, as depicted:

   >     template <class T, class charT = char, class traits = char_traits<charT>,
   >       class Distance = ptrdiff_t>
   >     class istream_iterator :
   >       public iterator<input_iterator_tag, T, Distance, const T*, const T&> {
   >     public:
   >       typedef input_iterator_tag iterator_category;
   >       typedef T value_type;
   >       typedef Distance difference_type;
   >       typedef const T* pointer;
   >       typedef const T& reference;
   >       […]
   >     };

7. Change 23.6.3 [ostream.iterator], class template `ostream_iterator` synopsis, as depicted:

   >     template <class T, class charT = char, class traits = char_traits<charT>>
   >     class ostream_iterator :
   >       public iterator<output_iterator_tag, void, void, void, void> {
   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;
   >       […]
   >     };

8. Change 23.6.4 [istreambuf.iterator], class template `istreambuf_iterator` synopsis, as depicted:

   >     template <class charT = char, class traits = char_traits<charT> >
   >     class istreambuf_iterator :
   >       public iterator<input_iterator_tag, charT,
   >                       typename traits::off_type, unspecified, charT> {
   >     public:
   >       typedef input_iterator_tag iterator_category;
   >       typedef charT value_type;
   >       typedef typename traits::off_type difference_type;
   >       typedef unspecified pointer;
   >       typedef charT reference;
   >       […]
   >     };

9. Change 23.6.5 [ostreambuf.iterator], class template `ostreambuf_iterator` synopsis, as depicted (editorial note: this removes a redundant "public:"):

   >     template <class charT = char, class traits = char_traits<charT>>
   >     class ostreambuf_iterator :
   >       public iterator<output_iterator_tag, void, void, void, void> {
   >     public:
   >       typedef output_iterator_tag iterator_category;
   >       typedef void value_type;
   >       typedef void difference_type;
   >       typedef void pointer;
   >       typedef void reference;
   >       […]
   >     public:
   >       […]
   >     };