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?
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 withoutput_iterator_tag
. All algorithms that require anOutputIterator
will Just Work with a mutableForwardIterator
, again there is no need for it to be tagged withoutput_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
andint*
have iterator categoryrandom_access_iterator_tag
, not your private tag and not anything to do withoutput_iterator_tag
. So you would probably be better off defining your own traits class rather than hoping to adapt the existingiterator_traits::iterator_category
to provide the information you want.