Reputation: 2043
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;
}
MatrixIterator
from std::iterator
so stl
would be able to understand it as a usual iterator ?I have read :
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.
Upvotes: 2
Views: 969
Reputation: 18562
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
).
Upvotes: 2