Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is std::iterator deprecated?

Tags:

c++

c++17

Template class std::iterator is set to be deprecated in C++17. Why so? It has been a handy way to make sure std::iterator_traits works, especially if you can make use of the default template arguments. Is there some other way of doing it in C++17?

like image 900
aschepler Avatar asked Apr 07 '17 01:04

aschepler


People also ask

Is iterator deprecated?

Conclusion. std::iterator is deprecated, so we should stop using it. Indeed, the next step after deprecation could be total removal from the language, just like what happened to std::auto_ptr .

What is std :: iterator?

std::iterator is the base class provided to simplify definitions of the required types for iterators.

Why are iterators useful C++?

Use of Iterators in C++ An iterator in C++ serves the following major purposes: The primary objective of an iterator is to access the STL container elements and perform certain operations on them. The internal structure of a container does not matter, since the iterators provide common usage for all of them.

What is Difference_type?

difference_type - a type that can be used to identify distance between iterators. value_type - the type of the values that can be obtained by dereferencing the iterator. This type is void for output iterators. pointer - defines a pointer to the type iterated over ( value_type )


2 Answers

From the proposal that suggested its deprecation:

As an aid to writing iterator classes, the original standard library supplied the iterator class template to automate the declaration of the five typedefs expected of every iterator by iterator_traits. This was then used in the library itself, for instance in the specification of std::ostream_iterator:

template <class T, class charT = char, class traits = char_traits<charT> >
class ostream_iterator:
  public iterator<output_iterator_tag, void, void, void, void>;

The long sequence of void arguments is much less clear to the reader than simply providing the expected typedefs in the class definition itself, which is the approach taken by the current working draft, following the pattern set in C++14 where we deprecated the derivation throughout the library of functors from unary_function and binary_function.

In addition to the reduced clarity, the iterator template also lays a trap for the unwary, as in typical usage it will be a dependent base class, which means it will not be looking into during name lookup from within the class or its member functions. This leads to surprised users trying to understand why the following simple usage does not work:

#include <iterator>

template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
   value_type data;  // Error: value_type is not found by name lookup 

   // ... implementations details elided ...
};

The reason of clarity alone was sufficient to persuade the LWG to update the standard library specification to no longer mandate the standard iterator adapators as deriving from std::iterator, so there is no further use of this template within the standard itself. Therefore, it looks like a strong candidate for deprecation.

You can also see STL's reasoning in LWG 2438. (h/t T.C.)


As for some other way of doing it, not really. You could basically implement your own version of std::iterator (which isn't too hard) or manually write out all of those typedefs (which isn't too hard either, and I actually prefer it for clarity).

like image 52
Barry Avatar answered Oct 24 '22 01:10

Barry


As Barry states, the working group has decided that explicitly declaring the types in the class is more readable and leads to less surprises than inheriting from std::iterator.

It's not too hard, though, to convert to the explicit types (below example taken from www.fluentcpp.com here). Given a class that was declared like so:

class MyIterator
  : public std::iterator<std::forward_iterator_tag, int, int, int*, int&>
{
  ...

The class without std::iterator becomes:

class MyIterator
{
public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = int;
    using difference_type = int;
    using pointer = int*;
    using reference = int&;

    // ...
like image 44
firebush Avatar answered Oct 24 '22 00:10

firebush