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 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.
Related
According to the [iterator.concepts.general]:
Otherwise, if iterator_traits names a specialization generated from the primary template, then
ITER_CONCEPT(I) denotes random_access_iterator_tag.
ITER_CONCEPT(I) may be std::random_access_iterator_tag,
even if I models input_iterator.
What is the purpose of this?
Why does c++ 20 iterator concept(such as std::forward_iterator) still checks whether the ITER_CONCEPT is derived from a certain tag?
Example:
template<class I>
concept forward_iterator =
input_iterator<I> &&
derived_from<ITER_CONCEPT(I), forward_iterator_tag> && //is this necessary?
incrementable<I> &&
sentinel_for<I, I>;
To be an X iterator, the iterator concept requires (among other things) two things. It is possible for a type to accidentally fulfill an iterator's syntactic requirements without intending to. As such, to be an X iterator, the prospective iterator type must declare that it intends to be (at least) an X iterator. This is done through the tag type, as retrieved through ITER_CONCEPT.
But iterators have an "inheritance" graph of sorts. All random access iterators are also bidirectional. So each iterator concept requires that the prospective iterator type fulfill the concept requirements of its "base" iterator concept.
These are separate requirements. Types can lie, after all, and the whole point of concepts is to keep types from lying. Just because a type claims to be a forward iterator does not mean it actually is one.
As for the purpose of this particular rule in ITER_CONCEPT, it is to bypass the defaulting mechanism defined for the legacy iterator_category. The idea is that if you haven't specified your iterator's tag type explicitly, then ITER_CONCEPT will assume the (second) most permissive one and then use C++20's concept checks to see what your iterator actually supports.
It doesn't mean that this iterator is definitely a random access iterator; it's saying "try (almost) anything, and if the concept doesn't fit, then that isn't it".
As shown here std::back_insert_iterator in pre- C++17 inherits from std::iterator while it doesn't in C++17. What is the reason for this change?
std::iterator is a convenience. It provides a handful of typedefs that code that uses iterators find useful. The preferred mechanism these days is std::iterator_traits, which is more flexible.
When an iterator is, in fact, a pointer it can't inherit from std::iterator, so iterator_traits has always been the way to get those typedefs. Having the typedefs in iterator types that are classes but not in iterator types that are pointers means that generic code can't use those members. Having them is minimally useful, and they're going away.
So since it was introduced I have been loving the for each in keywords to iterate STL collections.(I'm a very very big fan of syntactic sugar).
My question is how can I write a custom collection that can be iterated using these keywords?
Essentially, what APi do I need to expose for my collections to be iterable using these keywords?
I apologize if this sounds blunt, but please do not respond with "use boost", "don't write your own collections", or the like. Pursuit of knowledge, my friends. If it's not possible, hey, I can handle that.
I'd also very much so prefer not to have to inject an STL iterator into my collections.
Thanks in advance!
Here is a good explanation of iterable data structures (Range-Based loops):
In order to make a data structure iterable, it must work similarly to the existing STL iterators.
There must be begin and end methods that operate on that structure,
either as members or as stand-alone functions, and that return iterators to
the beginning and end of the structure.
The iterator itself must support an operator* method, an operator != method, and an operator++ method, either as members or as stand-alone functions.
Note, in C++11 there is an integrated support for range-based loops without the use of STL, though the above conditions hold for this as well. You can read about it at the same link above.
It's not really clear from your quesiton whether you're talking about std::for_each defined in the <algorithm> header, or the range-based for loop introduced in C++11.
However, the answer is similar for both.
Both operate on iterators, rather than the collection itself.
So you need to
define an iterator type which satisfies the requirements placed on it by the STL (the C++ standard, really). (The main things are that it must define operator++ and operator*, and a couple of other operations and typedefs)
for std::for_each, there is no 2. You're done. You simply pass two such iterators to std::for_each. For the range-based for loop, you need to expose a pair of these iterators via the begin() and end() functions.
And... that's it.
The only tricky part is really creating an iterator which complies with the requirements. Boost (even though you said you didn't want to use it) has a library which aids in implementing custom iterators (Boost.Iterator). There is also the std::iterator class which is intended as a base class for custom iterator implementations. But neither of these are necessary. Both are just convenience tools to make it easier to create your own iterator.
Is it possible to implement an any iterator with boost iterator facade?
I don't want to define implementation details in my baseclass
class Base
{
public:
typedef std::vector<int>::iterator iterator;//implementation detail
...
virtual iterator begin()=0;
virtual iterator end()=0;
};
or do i have to write one completely from scratch;
The code you've posted has fixed the type of iterators returned from Base and all it's implementantions to std::vector<int>::iterator which is probably not what you want. Jeremiah's suggestion is one way to go with one drawback: you loose compatibility with STL... I know of three implementations of a polymorphic iterator wrapper:
becker's any_iterator (which implements boost::iterator_facade)
the opaque_iterator library (google for it), or
Adobe's very interesting poly library which contains a hierarchy of STL conforming any_iterators.
The problem is harder than it might seem... I made an attempt myself mainly because I needed covariance in any_iterators type argument (any_iterator<Derived> should be automatically convertible to any_iterator<Base>) which is difficult to implement cleanly with STL like iterators. A C# like Enumerator<T> is easier to implement(*) (and imho generally a cleaner concept than STL-like pairs of iterators) but again, you "loose" the STL.
(*) = without 'yield' of course :-)
I think this may be what you're looking for:
any_iterator: Type Erasure for C++ Iterators
Here's a snippet from that page::
Overview
The class template any_iterator is the analog to boost::function for
iterators. It allows you to have a single variable and assign to it
iterators of different types, as long as these iterators have a
suitable commonality.
I tried to understand iterator implementation, and while playing around with the source, I saw this statement:
typedef output_iterator_tag iterator_category;
I don't understand how this typedef work within the class? What's the side effect does it provide? Can anyone walk me through this?
You need to read up on generic programming because you're not likely to get this answer.
"Output Iterator" is a concept that certain iterators match. Each iterator that is a realization of this concept has certain functionality associated with it. It's sort of like inheritance, but it isn't.
C++ doesn't have any such anything that represents concepts (was a proposed addition to C++0x but failed to make it). That being the case, we need various template constructs to allow us to associate a "tag" with an iterator type. By associating the output_iterator_tag type with an iterator we're claiming that our iterator type realizes the OutputIterator concept.
This becomes very important when you're trying to write algorithms that are as optimized as possible and also generic. For example, performing a sort with an iterator that can be incremented or decremented by an arbitrary value (other than 1 in other words) is more efficient than one that doesn't have this capability. Furthermore, in order to get a new iterator that's X distance from another can require different operations depending on the capabilities of the iterator. To write such an algorithm you use "tag dispatching". To explain this more fully, here's an implementation (untested) of std::advance that works both with iterators that have a += operator and ones that only have a ++ operator and is as fast as possible with both versions.
template < typename RandomAccessIterator >
RandomAccessIterator advance( RandomAccessIterator it
, int amount
, random_access_iterator_tag)
{ return it + amount; }
template < typename ForwardIterator >
ForwardIterator advance(ForwardIterator it, int amount, forward_iterator_tag)
{
for (;amount; --amount) ++it;
return it;
}
template < typename Iterator >
Iterator advance(Iterator it, int amount)
{
typedef typename std::iterator_traits<Iterator>::iterator_tag tag;
advance(it, amount, tag());
}
That's from memory so it's probably riddled with bugs (probably have a bunch of types wrong even)...but that's the idea. The iterator tags are types that are empty and also inherit from each other in exactly the same way as the concepts refine each other. For instance, a random access iterator IS a forward iterator. Thus random_access_iterator_tag is a derivative of forward_iterator_tag. Because of function overload resolution rules passing a random_access_iterator_tag to the function resolves to that version of the function rather than the forward_iterator_tag one.
Again, go read up on generic programming. It's essential to utilizing the full power of C++.
Oh, and finally... The typedef is there in the iterator's class definition because it's a nice, convenient place to put it. A default iterator_traits can the look for it there. You'll want to use iterator_traits rather than that definition though because raw pointers are iterators too and they can't have internal typedefs.
output_iterator_tag is an empty class. Its purpose is to allow algorithms to identify generic classifications of iterators which follow certain rules and provide particular operators. This allows for algorithms to provide a more specialized implementation of a given algorithm under certain conditions.
For example in VS2010's header, "std::distance"'s algorithm has two implementations depending on the 'iterator_category' typedef'd in the iterators passed in.
std::distance only requires an input iterator in order to calculate the distance between two iterators, but it might take linear 'O(n)' time to calculate the answer.
If however, the compiler figures out that a random access iterator is being used and can thereby take advantage of the subtraction operator to calculate the distance in constant time 'O(1)'.
I would recommend watching Stephan T. Lavavej's video where he goes a bit into type traits and their uses in the Standard Template Library.