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?
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 .
std::iterator is the base class provided to simplify definitions of the required types for iterators.
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.
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 )
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 fromunary_function
andbinary_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).
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&;
// ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With