user3059627
user3059627

Reputation: 119

What is the design purpose of iterator_traits?

The C++ standard library has both iterator and iterator_traits templates defined. It seemed that in general, the iterator_traits just extracts properties that defined explicitly in iterator. If a iterator_traits is to be used, one can use the corresponding iterator directly. If a specialization of certain type (e.g. T*) is required, a specialization of iterator could match the requirement. What's the benefit this indirection?

Upvotes: 2

Views: 1331

Answers (1)

eerorika
eerorika

Reputation: 238361

It seemed that in general, the iterator_traits just extracts properties that defined explicitly in iterator. If a iterator_traits is to be used, one can use the corresponding iterator directly.

Not all iterators can type aliases as members.

What's the benefit this indirection?

To allow all iterators to have a uniform interface. More specifically, pointers are iterators too and as non-class types, pointers cannot have members.

So, when for example the user of an iterator wants the answer to the question "What is the type of the object pointed by an_iterator_type", they cannot use an_iterator_type::value_type because that cannot be defined for all iterators - specifically pointers. What they can use is std::iterator_traits<an_iterator_type>::value_type which can be defined for all iterators - including pointers. That is the purpose of std::iterator_traits.


The standard defines the std::iterator_traits<T*> specialisations for pointers. Although you can, you don't need to define specialisations for custom iterator types because you can instead define the types as members, which will be used by the generic definition of std::iterator_traits.

The intention of std::iterator was to be optionally used as a base class to help define the member types for custom iterators. However its use was never necessary, it is considered to be a flawed design and its use has long been discouraged. Since C++17, it has been deprecated and it may be removed from future standards.

An example that hopefully demonstrates the problem of the design of std::iterator:

// using the deprecated std::iterator
struct iterator : std::iterator<
    std::input_iterator_tag,   // OK so far
    long,                      // can you guess what member this argument defines?
    long,                      // how about this?
    const long*,               // you can probably guess this one
    long>                      // still, no clue
{
    ...

// recommended way without using std::iterator
struct iterator
{
    using iterator_category = std::input_iterator_tag;
    using value_type = long;
    using difference_type = long;
    using pointer = const long*;
    using reference = long;
    ...

Upvotes: 13

Related Questions