In my project I have some custom classes, with roughly the structure below.
Point, which represents a 2D int coordinate
struct Point {
int x;
int y;
}
Line, which represents a line drawn between two Points
class Line {
Point start;
Point end;
}
Polygon, which represents the polygon that is defined by number of Points.
class Polygon {
private:
std::vector<Point> _vertices;
}
I'm trying to implement a custom iterator for Polygon, the goal being a syntax something like:
Polygon aPolygon;
Point somePoint;
for( auto line_it = aPolygon.begin(); line_it != aPolygon.end(); line_it++ ){
if( line_it->includes(somePoint) ){
// Do something
}
}
When iterating over Polygon the n:th element would be
Line( _vertices[n], _vertices[n+1] ),
and the last would be
Line( _vertices[_vertices.size() - 1], _vertices[0] )
How do I implement such an iterator, or otherwise acheive similar syntax with acceptable performance?
I'm looking through similar questions, but I've yet to find one similar enough for a comprehensive answer.
If possible I would prefer a STL solution that uses c++20 standard.
I realize the question was unecessarily vague, more specifically I'm asking how I can implement the *,-> and ++ operators for my iterator.
class Polygon {
public:
/* ... */
struct PolygonIterator {
using iterator_category = std::input_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = Line;
using pointer = value_type*;
using reference = value_type&;
explicit PolygonIterator( Point* ptr ) : m_ptr( ptr ) {}
reference operator*();
// ^ Should return Line reference, but I have Point in container?
PolygonIterator& operator++();
pointer operator->();
bool operator==(const PolygonIterator& other);
private:
Point* m_ptr;
};
PolygonIterator begin() { return PolygonIterator( &_vertices.front() ); }
PolygonIterator end() { return PolygonIterator( &_vertices.back() ); }
Looking at your code again, satisfying forward iterator requirements would be tricky, because you essentially generate the lines on the fly. Hence I suggest making an input iterator.
operator++ should just increment m_ptr, nothing unusual. But you might want to store an std::vector iterator instead of a pointer (then, if you enable iterator debuggning for standard containers, it will extend to your iterators).
Then you have two options:
Store the current Line inside of the iterator. Then * and -> return a reference and a pointer to it respectively. ++ will need to update this Line after incrementing the pointer/iterator.
Return the Line from operator* by value, and change using reference to Line to match the return type. This is unusal, but allowed for input iterators.
Then operator-> becomes tricky. It can't return a pointer (because there's no Line to point to), so it has to return a helper class by value, which in turn would store a Line (again by value), and overload -> to return a pointer to it. You probably should also change using pointer to match the type of this helper class.
Welcome into the world of containers which are not containers!
Since the beginning, standard library containers are expected to actually directly contain their objects. I could find 2 reference articles about that:
When Is a Container Not a Container? by Herb Sutter, and
To Be or Not to Be (an Iterator) by Eric Niebler
Long story made short your pseudo container is only a proxy container: objects exists elsewhere, and the container can only build proxies to them. It is not so uncommon and vector<bool> is such a container, and its iterators are only proxy iterators. Simply if you look into the sources of an implementation of the standard library, you will find every now and then special processing for vector<bool> in algorithm because vector<bool> iterators pretend being random access iterators when they cannot even meet the requirements of a forward container.
That means that your iterators will only be proxy iterators and their reference type will be an object (the proxy) instead of a true reference. Because of that they will be no more than simple input iterators. It is is acceptable for you, that will be enough, else you could have a look to the range library of C++20, which should start to provide some support to proxy containers and iterators.
Related
I am trying to build an iterator class in c++ for a class that has a 2d array of size 8x8 as its main data member. I want to iterate over the 2d array column wise.
I am trying to think about this in terms of how a vector iterator class is written.
How should I go about creating this Iterator class?
Would the constructor need to accept a double pointer (**obj) ? Assuming I do that, how would I perform increments while overloading the ++ operator for the double pointer?
This is what I have
class Iterator
{
public:
Iterator(Board **obj)
{
ptr = obj;
}
Iterator& operator++()
{
ptr++;
}
private:
Board **ptr;
};
First off, your given implementation is NOT correct. When you increment your pointer, you're incrementing it by one Board, not one position in the board. That's not at all what you want.
If you're going to implement iterators properly, you need to start with the containing class -- assuming you're actually talking about iterators so you can do something like:
for (int i: myBoard) {
}
and the compiler knows what to do.
class Board {
public:
class ForwardIterator { ... };
class ReverseIterator { ... };
ForwardIterator begin() { ... }
ForwardIterator end() { ... }. // Should return one position past the end
ReverseIterator rbegin() { ... }
ReverseIterator rend() { ... }. // One position before beginning
};
That's just a start. You also need const versions. You can probably clean this up with the use of templates, but you start to see -- it's not necessarily trivial.
Under the hood, the iterator can work however you want it to work. You can keep an int row, col for instance, and just move them accordingly. In the most simplest form, that's what I would do.
You also need operator= and operator!= so that you can compare iterators to detect past-beginning or past-ending.
Don't forget to also implement:
int & operator*() { return board[row][col]; }
A complete answer, done properly, is beyond the scope of Stack Overflow. This isn't a bad link: https://internalpointers.com/post/writing-custom-iterators-modern-cpp. But a google for "writing iterators c++" will yield a variety of useful links for the nitty gritty details.
Suppose I have a class encapsulating std container:
class Stash
{
list<int> Data;
public:
list<int>::const_iterator GetAccess() const { return Data.begin(); }
};
It's very convenient way of forcing the user to read the data in form of the iterator. However, I can't find the way other that comparing the iterator to container.end(). So, I would like to know if there's an option to do it solely by stdlib or I have to write iterator class myself (with can_advance method, for example).
Relevant question might be this one, but it asks whether the iterator is valid, not whether it can advance. I weren't able to find any information about the latter.
You can't do this, a single iterator does not contain the information when it is at the end of the sequence its pointing into.
Normally, this is solved by either providing a range (think std::make_pair(cont.begin(), cont.end())), or providing begin() and end() methods to your class, effectively making it a range.
Iterators work in pairs: an iterator that points to the beginning of a sequence and an iterator that points past the end of the sequence. That's why all the containers have begin() and end() member functions: so you can look at the sequence of values that the container manages.
It would be far more idiomatic to change the name of GetAccess to begin and to add end. Having end() would also make it possible to apply standard algorithms to the data.
What you seem to be asking for is a "lookahead" iterator. You could write a class to "adapt" an iterator to have lookahead, where the adaptor just stays one step ahead of your code:
template<class FwdIter>
class lookahead_iterator
{
public:
lookahead_iterator(const FwdIter& begin): cur_iter(begin), next_iter(++begin) {}
operator FwdIter() const { return cur_iter; }
lookahead_iterator<FwdIter>& operator ++() { cur_iter = next_iter++; return *this; }
// Other methods as needed.
private:
FwdIter cur_iter;
FwdIter next_iter;
};
Needless to say, this gets a lot more complicated if you need more than a forward iterator.
Lately I have been needing to implement small classes that generate a bunch of numbers. It would be very convenient if C++ had generators like python, but unfortunately it is not so.
So I have been thinking of how to best implement these types of objects, for easy iteration and composition. When we think of iterators over containers, they essentially only hold the index to an element, and the bulk of the information is in the container itself. This allows for several iterators to be referencing different elements within a collection at the same time.
When it come to state machines, it becomes apparent that the iterator will have to hold the whole state as several iterators need to be able to be independent. In that sense, the state machine class is more of a "builder" of these iterators which are the actual state machines.
As a toy example I have implemented the range generator (ala xrange in python), that can be used in loops:
// using range-for from c++11
for (auto i : range<int>(1, 30)) {
cout << i << endl;
}
The code can be found on my bitbucket.
That said, it is awkward to store the whole state within the iterator, since the end() iterator is created just for the sake of comparing the ending state, which wastes space if the state is a large collection of members.
Has there been anything done with simple linear state machines, and looping over them with iterators?
If you support only forward iteration, you might be able to get away with using a different type for end() then for begin(). Here's the basic idea
class iterator;
class iterator_end {
typedef ... value_type;
...
iterator& operator++ () { throw ... }
value_type operator* () { throw ... }
bool operator== (const iterator& e) const { return e == *this; }
}
class iterator {
typedef ... value_type;
..
iterator& operator++ () { ... }
value_type operator* () { ... }
bool operator== (const iterator_end& e) const { return are_we_done_yet }
}
class statemachine {
iterator begin() const { ... }
iterator_end end() const { ... }
}
I've never tries this though, so I can't guarantee that this will work. Your state-machine's iterator and const_iterator typedefs will specify a different type than end() returns, which may or may not cause trouble.
Another possibility is to go with a variation on pimpl which uses boost::optional. Put the iterator state into a separate class, and store it within a boost::optional within the iterator. Leave the state unset for the iterator returned by end(). You won't save any memory, but you avoid heap allocations (boost::optional doesn't do any, it uses placement new!) and initialization overhead.
I have a privately scoped Boost.BiMap in a class, and I would like to export a public view of part of this map. I have two questions about the following code:
class Object {
typedef bimap<
unordered_set_of<Point>,
unordered_multiset_of<Value>
> PointMap;
PointMap point_map;
public:
??? GetPoints(Value v) {
...
}
The first question is if my method of iteration to get the Point's associated with a Value is correct. Below is the code I'm using to iterate over the points. My question is if I am iterating correctly because I found that I had to include the it->first == value condition, and wasn't sure if this was required given a better interface that I may not know about.
PointMap::right_const_iterator it;
it = point_map.right.find(value);
while (it != point_map.right.end() && it->first == val) {
/* do stuff */
}
The second question is what is the best way to provide a public view of the GetPoints (the ??? return type above) without exposing the bimap iterator because it seems that the caller would have to know about point_map.right.end(). Any efficient structure such as a list of references or a set would work, but I'm a bit lost on how to create the collection.
Thanks!
The first question:
Since you are using the unordered_multiset_of collection type for the right side of your bimap type, it means that it will have an interface compatible with std::unordered_multimap. std::unordered_multimap has the member function equal_range(const Key& key) which returns a std::pair of iterators, one pointing to the first element that has the desired key and one that points to one past the end of the range of elements that have the same key. Using that you can iterate over the range with the matching key without comparing the key to the value in the iteration condition.
See http://www.boost.org/doc/libs/1_41_0/libs/bimap/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html and http://en.cppreference.com/w/cpp/container/unordered_multimap/equal_range for references.
The second question:
Constructing a list or other actual container of pointers or references to the elements with the matching values and returning that is inefficient since it's always going to require O(n) space, whereas just letting the user iterate over the range in the original bimap only requires returning two iterators, which only require O(1) memory.
You can either write a member function that returns the iterators directly, e.g.
typedef PointMap::right_const_iterator match_iterator;
std::pair<match_iterator, match_iterator> GetPoints(Value v) {
return point_map.right.equal_range(v);
}
or you can write a proxy class that presents a container-like interface by having begin() and end() member functions returning those two iterators, and have your GetPoints() member function return an object of that type:
class MatchList {
typedef PointMap::right_const_iterator iterator;
std::pair<iterator, iterator> m_iters;
public:
MatchList(std::pair<iterator, iterator> const& p) : m_iters(p) {}
MatchList(MatchList const&) = delete;
MatchList(MatchList&&) = delete;
MatchList& operator=(MatchList const&) = delete;
iterator begin() { return m_iters.first; }
iterator end() { return m_iters.second; }
};
It's a good idea to make it uncopyable, unmovable and unassignable (like I've done above by deleting the relevant member functions) since the user may otherwise keep a copy of the proxy class and try to access it later when the iterators could be invalidated.
The first way means writing less code, the second means presenting a more common interface to the user (and allows for hiding more stuff in the proxy class if you need to modify the implementation later).
What are Iterators in C++?
Iterators are a way of traversing a collection of objects. Typically, they allow you to access an STL (Standard Template Library) container sequentially in ways similar to accessing a classical C array with a pointer. To access an object through an iterator, you dereference it like a C pointer. To access the next object in a collection, you use the increment (++) operator. Some containers have multiple kinds of iterators that allow you to traverse the collection in different ways.
Though it initially seems fairly obvious, this is actually a rather deeper question than you may realize. Along with Paul McJones, Alexander Stepanov (designer of the original, for anybody who's not aware of that) recently released a book named Elements of Programming (aka EOP). The entirety of chapter six in that book is devoted specifically to iterators, and quite a bit of the rest of the book relates closely to iterators as well. Anybody who really wants to know iterators in full detail might consider reading this book.
Warning: EOP is not for the faint of heart. It's relatively short (~260 pages), but quite dense. Speaking from experience, the early going is a bit disconcerting. My initial reaction to the first chapter was more or less "well, this is so obvious it's hardly worth reading. I did start programming before last week, after all!"
Fortunately, I did look at the exercises, and tried to do a couple -- and even though I had thought of the subjects as obvious, the exercises demand rigorous proofs. It's a bit like being asked to prove (in a mathematical sense) that water is wet. You end up just about needing to read the chapter a couple of times just to get past your own preconceived notion that you already know the answers, so you can look at the real question -- what does "wet" really mean; what are the fundamental characteristics of "wetness"?
http://en.wikipedia.org/wiki/Iterator
Something that lets you go through everything in an array, one by one.
In c++, i think you're talking about "for_each" ... As far as I know, C++ doesn't actually have "foreach" unlike languages like C#. However, the standard template library has it.
From p. 80 of Accelerated C++:
An iterator is a value that
Identifies a container and an element in the container
Lets us examine the value stored in that element
Provides operations for moving between elements in the container
Restricts the available operations in ways that correspond to what the container can handle efficiently
They're a representation of a position within a sequence. On their own they're little more than curiosities, but when dereferenced they result in the value contained within the sequence at the position it represents.
If you come from higher-level languages like Java or Python, you may have noticed C++ doesn't have any built-in complex types but only primitives like int, double or char. Since C++ was designed to be extremely efficient, whenever you need to use any collection type that is used to hold other values, it makes sense to create a new custom class. In fact, this is the way how C++ combines lower-level control and higher-level abstractions.
The Standard Template Library provides a standartised collection of those classes that you can use to hold multiple values under a single entity. Primarily, they were created because raw C arrays are not flexible enough and the containers provide developers with smoother developer experience as they:
dynamically expand and shrink without any developer effort;
provide multiple useful interfaces with the data (size(), upper_bound(), etc);
simplify memory management with Resource Acquisition is Initialisation.
So far, so good. Standard containers like vector or list give developers greater flexibility without much performance loss. However, since they are custom classes defined with C++ semantics, they need to provide also a way to access the data they hold. One could argue a simple operator[] or next() method could do the trick, and indeed you can do this, however the STL took inspiration from C and created a way to be able to access container items not depending on the container object itself: iterators.
Under the hood, iterator is nothing but an object that wraps a pointer to a value with a few operator overloading. You can use iterators in a similar way how you use pointers to array:
you can pass iterators around and iterate through containers even if you don't have the access to the container objects themselves;
you can dereference and move iterator with incrementation.
This is the primary purpose of iterators: to serve as pointers to container items. Because different containers store different items in different ways (std::vector uses contiguous block of memory, std::list stores nodes elsewhere connected with pointers, std::map uses hashing key in associative array), iterators are useful to provide a common interface that will be implemented in every separate container. In fact, this is the very reason that allows containers like std::vector, std::array or std::map to be enumerated with range-based for loops:
std::vector<int> grades = {4, 5, 1, 8, 10};
for (int grade : grades) std::cout << grade << " ";
//-> 4 5 1 8 10
This for loop is just syntactic sugar for using iteration:
std::vector<int> grades = {4, 5, 1, 8, 10};
std::vector::iterator it = grades.begin();
for (; it != grades.end(); ++it) std::cout << grade << " ";
//The output is the same.
You may have noticed some common interfaces iterators use, precisely they:
overload the * operator to dereference an item;
overload the ++ operator to move the iterator one item forward;
overload the == and != operators to compare if they point to the same value;
are usually defined as a nested friend class (you access them with <container>::iterator, although you can entirely define iterator as a separate class.
Notice also that all containers that support containers should provide begin() method that returns the iterator to the first item, as well as end() to return an iterator to the item after the last one. The reason why it points to the location past the final one is because it is used to evaluate if the iterator exhausted all items: had end() pointed to the last item, the looping condition would be it <= grades.end(). Instead pointing to the next location after the container allows it evaluate it with a simple less check, which is the same reason why arrays begin with zero. Aside from them, there's also rbegin() and rend() functions that provide reversed iterator that goes from the end to the start and its ++ operator actually goes to the beginning.
Implementing a custom iterator
To make it completely clear, let's implement our own custom iterator for a wrapper around plain arrays.
template<typename T, unsgined int Capacity> class Array {
T data[Capacity];
int count;
friend class Iterator;
public:
Array(const std::initializer_list args) {
for (int step = 0; step < args.size(); step++)
data[step] = args[step;
}
int size() : count;
T& operator[](int index) {
if (index < 0 || index > capacity) throw
std::out_of_range("Index out of range.");
return data[index];
}
Iterator<T> begin() {
return &data; //Pointer to array yield the
//address to their first item.
}
Iterator<T> end() {
return &(data + Capacity);
}
};
template<typename T> class Iterator {
T* reference;
public:
Iterator(const Array<T>& array) {
reference = array.begin();
}
T* operator*() {
return reference;
}
Iterator<T> operator++() {
return ++reference; //This is array-specific implementation detail.
}
bool operator!=(const Iterator<T>& other) : *reference != *other;
};
int main() {
Array<int> array = {4, 5, 10, 12, 45, 100};
Iterator<int> it = array.begin();
while (it != array.end()) {
std::cout << *it;
++it;
}
return 0;
}
As you can see, dividing iterator as a separate class creates a need to specify its type separately as well, which is the reason why it's usually defined as a nested class in its container.
There is also <iterator> header that provides some useful facilities for standard iterators, such as:
next() function that increments the iterator;
prev() function that returns the iterator ` step before;
advance(int) that moves iterator n steps forward;
overloaded operators to compare iterators;
other iteration-related additions.
If you need to write a custom iterator for your own highly-specific container that isn't present in STL, you should remember that iterators are used as a median between containers and algorithms, and for your own container you should pick the proper type of iterator (input, output, forward, bidirectional or random access) to support a number of standard algorithms out of the hand.