# iterator_category

Category: iterators | Component type: function

### Prototype

`Iterator_category` is overloaded; it is in fact six different functions.

    inline output_iterator_tag iterator_category(const output_iterator&);

    template <class T, class Distance>
    inline input_iterator_tag
    iterator_category(const input_iterator<T, Distance>&);

    template <class T, class Distance>
    inline forward_iterator_tag
    iterator_category(const forward_iterator<T, Distance>&);

    template <class T, class Distance>
    inline bidirectional_iterator_tag
    iterator_category(const bidirectional_iterator<T, Distance>&);

    template <class T, class Distance>
    inline random_access_iterator_tag
    iterator_category(const random_access_iterator<T, Distance>&);

    template <class T>
    inline random_access_iterator_tag iterator_category(const T*);

### Description

`Iterator_category` is an iterator tag function: it is used to determine the category to which an iterator belongs. Specifically, every iterator must belong to a type that is a model of the concept Output Iterator, Input Iterator, Forward Iterator, Bidirectional Iterator, or Random Access Iterator. [1] `Iterator_category` returns an object of class `output_iterator_tag`, `input_iterator_tag`, `forward_iterator_tag`, or `random_access_iterator_tag`, depending on which concept the type of `iterator_category`'s argument is a model of. [2] This information is useful in the case of an algorithm that has a sensible definition for more than one category of iterator, but whose definition is different depending on the category.

Although `iterator_category` looks like a single function whose return type depends on its argument type, in reality it is a set of functions; the name `iterator_category` is overloaded. The function `iterator_category` must be overloaded for every iterator type.

In practice, ensuring that `iterator_category` is defined requires essentially no work at all. It is already defined for pointers, and for the base classes `input_iterator`, `output_iterator`, `forward_iterator`, `bidirectional_iterator`, and `random_access_iterator`. If you are implementing a new type of forward iterator, for example, you can simply derive it from the base class `forward_iterator`; this means that `iterator_category` (along with `distance_type` and `value_type`) will automatically be defined for your iterator. These base classes are empty: they contain no member functions or member variables, but only type information. Using them should therefore incur no overhead.

Note that, while the function `iterator_category` was present in the original STL, it is no longer present in the most recent draft C++ standard: it has been replaced by the `iterator_traits` class. At present both mechanisms are supported [3], but eventually `iterator_category` will be removed.

### Definition

Defined in the standard header iterator, and in the nonstandard backward-compatibility header iterator.h. This function is no longer part of the C++ standard, although it was present in early drafts of the standard. It is retained in this implementation for backward compatibility.

### Requirements on types

The argument of `iterator_category` must be an iterator.

### Preconditions

None. `Iterator_category`'s argument is even permitted to be a singular iterator.

### Complexity

At most amortized constant time. In many cases, a compiler should be able to optimize away `iterator_category` entirely.

### Example

`Reverse` can be implemented for either Bidirectional Iterators or for Random Access Iterators, but the algorithm for Random Access Iterators is more efficient. Consequently, `reverse` uses `iterator_category` to select whichever algorithm is appropriate for the iterator type. This dispatch takes place at compile time, and should not incur any run-time penalty.

    template <class BidirectionalIterator>
    void __reverse(BidirectionalIterator first, BidirectionalIterator last,
                   bidirectional_iterator_tag) {
        while (true)
            if (first == last || first == --last)
                return;
            else
                iter_swap(first++, last);
    }

    template <class RandomAccessIterator>
    void __reverse(RandomAccessIterator first, RandomAccessIterator last,
                   random_access_iterator_tag) {
        while (first < last) iter_swap(first++, --last);
    }

    template <class BidirectionalIterator>
    inline void reverse(BidirectionalIterator first, BidirectionalIterator last) {
        __reverse(first, last, iterator_category(first));
    }

### Notes

[1] The STL also defines one other concept, Trivial Iterator. This concept is introduced only for conceptual clarity, however, in order to separate the axioms related to an object that refers to another object from those related to iteration over a range. In fact, the STL does not define any types that are Trivial Iterators. Although built-in C pointers may be Trivial Iterators, the C type system does not allow a distinction between pointers that are Trivial Iterators and pointers that are Random Access Iterators into C arrays. Consequently, there is no Trivial Iterator category tag.

[2] Any type that is a model of Forward Iterator is also a model of Input Iterator, any type that is a model of Bidirectional Iterator is also a model of Forward Iterator, and any type that is a model of Random Access Iterator is also a model of Bidirectional Iterator. `Iterator_category` must return a tag representing the most specific concept that its argument is a model of. If its argument is a `vector::iterator`, for example, then it must return `random_access_iterator_tag`.

[3] The `iterator_traits` class relies on a C++ feature known as partial specialization. Many of today's compilers don't implement the complete standard; in particular, many compilers do not support partial specialization. If your compiler does not support partial specialization, then you will not be able to use `iterator_traits`, and you will have to continue using the functions `iterator_category`, `distance_type`, and `value_type`. This is one reason that those functions have not yet been removed.

### See also

The Iterator Tags overview, `iterator_traits`, `distance_type`, `value_type`, `output_iterator_tag`, `input_iterator_tag`, `forward_iterator_tag`, `bidirectional_iterator_tag`, `random_access_iterator_tag`

Copyright © 1999 Silicon Graphics, Inc. All Rights Reserved. TrademarkInformation