Generic iterator - c++

I am trying to find a generic way of accessing a set of containers. I have a standard vector and list in addition to another custom list.
The custom list defines an iterator;
class Iterator: public std::iterator<std::forward_iterator_tag, T> {
// ...
}
Iterator begin() {
return (Iterator(root));
}
Iterator end() {
return (Iterator(NULL));
}
with the appropriate operators overloaded.
Ideally, I would like to do this;
class Foo {
public:
Foo() {
std::list<int> x;
std::vector<int> y;
custom_list<int> z;
iter = x.begin(); // OR
iter = y.begin(); // OR
iter = z.begin();
// ...
};
private:
std::iterator<int> iter;
};
But obviously these are all iterators of different types. I can assume all the containers are of the same type however.
Is there an elegant way to solve this problem?

Here are some articles you might find of interest
Giving STL Iterators a Base Class
Type Erasure for C++ Iterators
any_iterator Class Reference

Better late than never...
The latest issue of C-Vu turned up and guess what was in it: That's right, iterators that do exactly what you wanted.
Unfortunately you need to become a member of the ACCU to view the magazine (the article references the Overload article from 2000 that David links to). But for a measly price a year you get a nice magazine to read, conferences and user groups. When you become a member you can view PDF's of the back issues so what are you waiting for?

A case of being careful what you ask for. The any_iterator classes you see work on an unbounded set of iterator types. You only have three, which you know up front. Sure, you might need to add a fourth type in the future, but so what if that takes O(1) extra lines of code ?
The big advantage of a closed set of possible contained types is that you have an upper bound on sizeof(), which means you can avoid the heap and the indirection it brings. Basically, stuff them all in a boost::variant and call apply_visitor.

Related

C++ returning iterators to two or more class containers

I'm building an C++ API just for learning purposes and I'll need a class
with two containers. Suppose they're initially of type vector<>.
class MyClass
{
private:
std::vector<int> containerA;
std::vector<double> containerB;
public:
std::vector<int> *getContainerA();
std::vector<double> *getContainerB();
};
But if someday I'll have to change the type of these containers (to list, for instance), I would not want that the users of this API needed to change anything in their code.
So, considering that containerA and containerB types were changed, when using the getters above, which return vector<>, API users would need to change their code to match the new type of API's containers.
I think that return iterators instead of vector<> can help me with that.
class MyClass
{
private:
std::vector<int> containerA;
std::vector<double> containerB;
public:
std::vector<int>::iterator beginContainerA() { return containerA.begin(); }
std::vector<int>::iterator endContainerA() { return containerA.end(); }
std::vector<double>::iterator beginContainerB() { return containerB.begin(); }
std::vector<double>::iterator endContainerB() { return containerB.end(); }
};
Is this the way how things are done? Is there a better way? Thank you.
I recommend combining πάντα ῥεῖ's idea and yours: Both define a type alias, and return iterators:
typedef std::vector<int> ContainerAType;
ContainerAType::iterator beginContainerA();
Also, you'll need a const version as well, so that you can use the iterators on const instances:
ContainerAType::const_iterator beginContainerA() const;
Consider whether non-const access is even needed.
Consider returning a range of iterators instead:
boost::iterator_range<ContainerAType::iterator> containerA();
However, to truly protect the client from any changes, you will need to use type erasing iterator. With type erasure, the client does not even need to recompile, if you change from vector to list (but you also have to use pimpl pattern, to achieve that). You could even stop using a container entirely, and return custom iterators, that generate the data.
Boost has you covered: http://www.boost.org/doc/libs/1_54_0/libs/range/doc/html/range/reference/ranges/any_range.html Type erasing iterators do have some overhead, due to using a virtual function call internally.
Rather use getters like
const std::vector<int>& getContainerA() const { return containerA; }
and let your clients use
std::vector<int>::const_iterator
from the reference.
But if someday I'll have to change the type of these containers (to list, for instance), I would not want that the users of this API needed to change anything in their code.
Also you can use a class specific typedef to expose the underlying container type:
typedef std::vector<int> ContainerAType;
const ContainerAType& getContainerA() const { return containerA; }
Note that handing out iterators is bad, in the sense that these may become invalid upon changes to the underlying containers.
If a client should be notified about changes, you'll need a separate mechanism like e.g. an Observer .

How to hide my inner collection but allow the user iterate over him ?

I have many class that has inside list<cats> , and i want to allow users that use my class to iterate over the cats i have, so i give them access to a const iterator by writing the following function :
list<cats>::const_iterator GetIterator()
{
//return the iterator
}
Now i want to change my implementation of the class and use vector instead of list, so i need to return a const iterator of vector.
The problem is that every one that uses my class now need to change their code from list<cats>::const_iterator to vector<cat>::const_iterator.
If all the iterators where to inherit from "forward iterator" it would be very useful.
My major question is how i solve this problem, i don't want to inherit from a collection.
Another very related question is why the designers of STL chose not to inherit iterators one from another ? (for example random access iterators could have inherit from forward iterators, he have all it's functionality)
I did pretty extensive search before i asked my question but couldn't find the solution.
The closest thing i found to my question is this, but it is not exactly my question.
Give access to encapsulated container
Expose an iterator type from your class, e.g:
class a
{
vector<int> g;
public:
typdef vector<int>::const_iterator const_iterator;
const_iterator begin() const
{ return g.begin(); }
: // etc
};
If the users can recompile the code you can use
typedef list<cats> CatList;
in your include file. Then, if you want to change the container, change it to
typedef vector<cats> CatList;
and the users would use e.g.
CatList::iterator it;
However this is not a good practice; the iterators of different containers may look equal but behave differently e.g. deleting an item from a vector invalidates all iterators but doing the same on list affects only iterator of deleted item. Not mentioning the case if some day you want to use std::map<some_key,cats>.
I agree with Nim's answer and wanted to offer the style I follow which I think makes maintenance easier since now changing the underlying container type requires no work at all for users of your class and very little work for you when maintaining your class.
class A
{
// change only this to change the underlying container:
// Don't Repeat Yourself!
using container_t = std::vector<int>;
public:
// constructor from a copy of a container
A(container_t source)
: _myContainer { std::move(source) }
{}
// this derived type is part of the public interface
using const_iterator_t = container_t::const_iterator;
// following your function naming style...
const_iterator_t GetIterator() const { return /* some iterator of _myContainer */; }
const_iterator_t GetEnd() const { return std::end(_myContainer); }
private:
container_t _myContainer;
};

Creating my own Iterators for non stl container

I have a class that manage data.
I wish to return only a part of the data that is inside it, but since it is a process that will be done multiple times I do not wish to just copy the data inside a container and return the container.
It would be nice if I could just send a reference or something similar. Iterators come to mind. but since I use Eigen3 Matrix (which does not have iterators (2D matrix anyway))
I am thinking of emulating(?) the iterators behavior,
something like that:
typedef unsigned int Index;
class MatrixIterator
{
public:
MatrixIterator(Eigen::MatrixXd *m, Index min, Index max):
_col(0), _index(0), _min(min), _max(max), _matrix(m)
{}
void operator++ ()
{
if (_index + _min + 1 != _max)
_index++;
}
void operator--()
{
if (_index != _min)
_index--;
}
double operator*()
{
return _matrix->operator() (_index + _min, _col);
}
void setCol(Index col) { _col = col; }
Index min() { return _min; }
Index max() { return _max; }
private:
// the matrix is 2D we can select
// on which column we want to iterate
Index _col;
// current position
Index _index;
// select the range on which the user can iterate
Index _max;
Index _min;
// the matrix on which we want to iterate over
Eigen::MatrixXd* _matrix;
}
I never really used iterators before, is it correct ?
Can I inherit my MatrixIterator from std::iterator so stl would be able to understand it as a usual iterator ?
Do you know a better way to do something similar ?
I have read :
Creating my own Iterators - which does not really speak of implementing iterators since they use vector iterator
http://www.cplusplus.com/reference/iterator/
How to use iterator to iterate a 2D vector?
EDIT : I want to iterate over only a part of the matrix (that is why I have _min and _max), the data I am manipulating are time series so the data are already ordered.
I think we can consider MatrixIterator as a response to a data query.
I never really used iterators before, is it correct ?
It's a good start. The idea is correct, but you are missing a few things. First, you don't have enough operators. Make sure you check the reference and provide every operator that you can sensibly provide (the only ones that may or may not be useful are random-access operators, because it could be harder to implement for this case). Second, you need to provide the iterator traits for your iterator class. This is usually done by creating the necessary nested typedefs in your iterator class (you could also specialize the std::iterator_traits template for your class, but I would say that this is only when you really cannot add the nested typedefs).
Can I inherit my MatrixIterator from std::iterator so stl would be able to understand it as a usual iterator ?
No, you should not, in general, inherit from the std::iterator class. The STL is a template library (generic programming (GP)) and therefore, does not use the base-class inheritance model as in OOP. The STL algorithms take iterators as template arguments, and will generically use them as required by the algorithm (or as possible by the iterator_category trait associated to the iterator type). This is generic programming, not object-oriented programming, it's apples and oranges.
Do you know a better way to do something similar ?
Well, one convenient way to do this is by using a class template like boost::iterator_facade (see ref) which provides a sort of automated "fill in the blanks" mechanism creating iterators. It uses the well-known and very useful Curiously Recurring Template Pattern (or CRTP for short). This is useful because implementing all the operators required for iterators can be quite verbose and repetitive, and the usually only really rely on just a few core operations (which is all you need to "fill in" when using a CRTP class like boost::iterator_facade).

Yield from C# to C++, dealing with containers

Actually, I have a design question here. Its very simple but the point is:
I have one C++ class that has a STL vector declared as a private member. But the clients of that class need to iterate over this vector.
In C# we have a very handy statement, the Yield, that in cases like that, you write a function returning an IEnumerable and it "yields" you a nice way to iterate over a private container inside that class.
I'm just trying to find an elegant solution for C++, instead of using methods like GetValue(int idx).
Any suggestions?
Example:
class Fat
{
public:
Fat();
// some code here ...
private:
void LoadSectors(SECT startPoint);
std::vector<SECT>sectors;
};
class Storage
{
public:
Storage(string CompoundFile);
//For example, this method will receive a ref to my fat system and iterate over
//the fat array in order to read every sector.
LoadStrem(Fat& fat);
};
This is far simple example.
There's no syntactic sugar in C++ analogous to yield in C#. If you want to create a class, instances of which should be iterable in the same way stock STL collections are, then you have to implement an iterator for your class, expose it as ::iterator on your type, and provide begin() and end() member functions.
You can either create an accessor function which returns a reference (or preferably const reference) to the vector, or you can create begin() and end() accessor functions which return the appropriate vector iterators.
It always hurts when you need to publish the innards of your class...
You may be able to solve it by providing algorithms as the stl does: provide a foreach function on the object's interface.
class S {
std::vector<int> v;
public:
//... and some methods to populate the vector
template< typename F > F& foreach( F& f ) {
return std::for_each( v.begin(), v.end(), f );
}
};
This way, the class remains 'closed', but you have the flexibility you need. You can also add a copy function, and maybe a transform; these are the ones I most frequently need.
Let your class expose iterators.
class Fat
{
public:
typedef std::vector<SECT>::iterator iterator;
iterator begin() { return sectors.begin(); }
iterator end() { return sectors.end(); }
Fat();
// some code here ...
private:
void LoadSectors(SECT startPoint);
std::vector<SECT>sectors;
Then the surrounding code can traverse the elements of the vector freely, through just a pair of iterators.

Returning an 'any kind of input iterator' instead of a vector::iterator or a list::iterator [duplicate]

This question already has answers here:
Generic iterator
(3 answers)
Closed 8 years ago.
Suppose I want to implement in C++ a data-structure to store oriented graphs. Arcs will be stored in Nodes thanks to STL containers. I'd like users to be able to iterate over the arcs of a node, in an STL-like way.
The issue I have is that I don't want to expose in the Node class (that will actually be an abstract base class) which STL container I will actually use in the concrete class. I therefore don't want to have my methods return std::list::iterator or std::vector::iterator...
I tried this:
class Arc;
typedef std::iterator<std::random_access_iterator_tag, Arc*> ArcIterator; // Wrong!
class Node {
public:
ArcIterator incomingArcsBegin() const {
return _incomingArcs.begin();
}
private:
std::vector<Arc*> _incomingArcs;
};
But this is not correct because a vector::const_iterator can't be used to create an ArcIterator. So what can be this ArcIterator?
I found this paper about Custom Iterators for the STL but it did not help. I must be a bit heavy today... ;)
Try this:
class Arc;
class Node {
private:
std::vector<Arc*> incoming_;
public:
typedef std::vector<Arc*>::iterator iterator;
iterator incoming_arcs_begin()
{ return incoming_.begin(); }
};
And use Node::iterator in the rest of the code. When/if you change the container, you have to change the typedef in a single place. (You could take this one step further with additional typedef for the storage, in this case vector.)
As for the const issue, either define vector's const_iterator to be your iterator, or define double iterator types (const and non-const version) as vector does.
Have a look at Adobe's any_iterator: this class uses a technique called type erase by which the underyling iterator type is hidden behind an abstract interface. Beware: the use of any_iterator incurs a runtime penalty due to virtual dispatching.
I want to think there should be a way to do this through straight STL, similar to what you are trying to do.
If not, you may want to look into using boost's iterator facades and adaptors where you can define your own iterators or adapt other objects into iterators.
To hide the fact that your iterators are based on std::vector<Arc*>::iterator you need an iterator class that delegates to std::vector<Arc*>::iterator. std::iterator does not do this.
If you look at the header files in your compiler's C++ standard library, you may find that std::iterator isn't very useful on its own, unless all you need is a class that defines typedefs for iterator_category, value_type, etc.
As Doug T. mentioned in his answer, the boost library has classes that make it easier to write iterators. In particular, boost::indirect_iterator might be helpful if you want your iterators to return an Arc when dereferenced instead of an Arc*.
Consider using the Visitor Pattern and inverting the relationship: instead of asking the graph structure for a container of data, you give the graph a functor and let the graph apply that functor to its data.
The visitor pattern is a commonly used pattern on graphs, check out boost's graph library documentation on visitors concepts.
If you really don't want the client's of that class to know that it uses a vector underneath, but still want them to be able to somehow iterate over it, you most likely will need to create a class that forwards all its methods to std::vector::iterator.
An alternative would be to templatize Node based on the type of container it should use underneath. Then the clients specifically know what type of container it is using because they told them to use it.
Personally I don't think it usually makes sense to encapsulate the vector away from the user, but still provide most (or even some) of its interface. Its too thin of an encapsulation layer to really provide any benefit.
I looked in the header file VECTOR.
vector<Arc*>::const_iterator
is a typedef for
allocator<Arc*>::const_pointer
Could that be your ArcIterator? Like:
typedef allocator<Arc*>::const_pointer ArcIterator;
You could templatize the Node class, and typedef both iterator and const_iterator in it.
For example:
class Arc {};
template<
template<class T, class U> class Container = std::vector,
class Allocator = std::allocator<Arc*>
>
class Node
{
public:
typedef typename Container<Arc*, Allocator>::iterator ArcIterator;
typedef typename Container<Arc*, Allocator>::Const_iterator constArcIterator;
constArcIterator incomingArcsBegin() const {
return _incomingArcs.begin();
}
ArcIterator incomingArcsBegin() {
return _incomingArcs.begin();
}
private:
Container<Arc*, Allocator> _incomingArcs;
};
I haven't tried this code, but it gives you the idea. However, you have to notice that using a ConstArcIterator will just disallow the modification of the pointer to the Arc, not the modification of the Arc itself (through non-const methods for example).
C++0x will allow you do this with automatic type determination.
In the new standard, this
for (vector::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr
can be replaced with this
for (auto itr = myvec.begin(); itr != myvec.end(); ++itr)
By the same token, you will be able to return whatever iterator is appropriate, and store it in an auto variable.
Until the new standard kicks in, you would have to either templatize your class, or provide an abstract interface to access the elements of your list/vector. For instance, you can do that by storing an iterator in member variable, and provide member functions, like begin() and next(). This, of course, would mean that only one loop at a time can safely iterate over your elements.
Well because std::vector is guaranteed to have contiguous storage, it should be perfect fine to do this:
class Arc;
typedef Arc* ArcIterator;
class Node {
public:
ArcIterator incomingArcsBegin() const {
return &_incomingArcs[0]
}
ArcIterator incomingArcsEnd() const {
return &_incomingArcs[_incomingArcs.size()]
}
private:
std::vector<Arc*> _incomingArcs;
};
Basically, pointers function enough like random access iterators that they are a sufficient replacement.