Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canonical way to define forward output iterator

How does one define forward-output-iterators in C++11 in a canonical way?

According to the standard a forward_iterator is only a input_iterator. So the corresponding forward_iterator_tag only extends input_iterator_tag. If we are using std::iterator to define our iterators, what tag do we use for a forward-output-iterator?

Is it canonical to define a private tag that extends both forward_iterator_tag and output_iterator_tag or is there a better solution?

like image 527
MFH Avatar asked Dec 27 '12 22:12

MFH


People also ask

How do you use a forward iterator?

Forward iterators are used to read the contents from the beginning to the end of a container. Forward iterator use only increments operator (++) to move through all the elements of a container. Therefore, we can say that the forward iterator can only move forward. A Forward iterator is a multi-pass iterator.

What is a forward iteration?

A Forward Iterator is an iterator that corresponds to the usual intuitive notion of a linear sequence of values. It is possible to use Forward Iterators (unlike Input Iterators and Output Iterators) in multipass algorithms.

What is the purpose of iterator elaborate forward bidirectional and random access iterators with suitable examples?

Bidirectional iterators are the iterators used to access the elements in both the directions, i.e., towards the end and towards the beginning. A random access iterator is also a valid bidirectional iterator. Many containers implement the bidirectional iterator such as list, set, multiset, map, multimap.

What is an output iterator?

An Output Iterator is a type that provides a mechanism for storing (but not necessarily accessing) a sequence of values.


1 Answers

The canonical thing to do is to inherit from std::iterator<std::forward_iterator_tag, T> only. Iterators have only one category.

The standard has no algorithms (or other uses) for an output iterator that is also a forward iterator. All uses of output iterators in the standard require only single-pass.

Instead, the standard has the idea of mutable vs. immutable iterators of categories forward/bidi/randomaccess. All the algorithms that need to write through iterators, and that require better than single-pass, also read through the same iterators they write through. This is std::remove, std::sort and other mutating algorithms.

The difference between mutable and immutable iterators is not detected by iterator tag, it's determined by whether the assignment expressions are well-formed. So for example if you pass an iterator to std::sort that's immutable, then the algorithm won't compile anyway, so there's generally no need for an input iterator to also be tagged with output_iterator_tag. All algorithms that require an OutputIterator will Just Work with a mutable ForwardIterator, again there is no need for it to be tagged with output_iterator_tag.

If you have different needs from those of the standard algorithms then I can't immediately think of a reason that your proposal won't work for your iterators. But it won't detect mutable standard iterators. For example std::deque<int>::iterator and int* have iterator category random_access_iterator_tag, not your private tag and not anything to do with output_iterator_tag. So you would probably be better off defining your own traits class rather than hoping to adapt the existing iterator_traits::iterator_category to provide the information you want.

like image 104
Steve Jessop Avatar answered Sep 19 '22 00:09

Steve Jessop