STL iterator: "dereferencing" iterator to a temporary. Is it possible?
I'm writing a 3D grid for my scientific software and I need to iterate through the nodes of the grid to get their coordinates. Ins开发者_开发问答tead of holding each node object in the container I'd rather like to just calculate the coordinates on the fly while iterating. The problem is that stl::iterator requires to return reference to a value as a result of operator*()
, or pointer for operator->()
.
Some of the code below:
class spGridIterator {
public:
typedef forward_iterator_tag iterator_category;
typedef spVector3D value_type;
typedef int difference_type;
typedef spVector3D* pointer;
typedef spVector3D& reference;
spGridIterator(spGrid* gr, int index);
spGridIterator& operator++();
spGridIterator& operator++(int);
reference operator*() const;
pointer operator->() const;
private:
spGrid* m_grid;
int m_idx;
};
spGridIterator::reference spGridIterator::operator*() const {
// return m_grid->GetPoint(m_idx);
}
spGridIterator::pointer spGridIterator::operator->() const {
// return m_grid->GetPoint(m_idx);
}
This method queries the node coordinates by index provided
spVector3D spGrid::GetPoint(int idx) const {
// spVector3D vec = ... calculate the coordinates here ...
return vec;
}
Any input on this?
Thanks in advance, Ilya
You could use a member variable to hold the grid point it is currently pointing to:
class spGridIterator {
public:
typedef forward_iterator_tag iterator_category;
typedef spVector3D value_type;
typedef int difference_type;
typedef spVector3D* pointer;
typedef const spVector3D* const_pointer;
typedef const spVector3D& const_reference;
typedef spVector3D& reference;
spGridIterator(spGrid* gr, int index);
spGridIterator& operator++();
spGridIterator& operator++(int);
reference operator*();
const_reference operator*() const;
pointer operator->();
const_pointer operator->() const;
private:
spGrid* m_grid;
int m_idx;
mutable spVector3D CurrentPoint;
};
Then the dereference operator could look like this:
spGridIterator::const_reference spGridIterator::operator*() const {
CurrentPoint = m_grid->GetPoint(m_idx);
return CurrentPoint;
}
Thanks to @greg for pointing out that CurrentPoint
needs to be mutable
for this to work. This would be a lazy implementation (only retrieving the point when the iterator is actually dereferenced). An eager implementation would update the CurrentPoint
member in the mutator methods of the iterator (the operator++
variants in this example), making the mutable
superfluous.
I know this post is too old but just because I had the same "problems" and google brought me here, I will add my two cents, here is what I found:
At least in the C++ library there are many iterator types, each one declaring some related semantics. The types are
- Input iterators
- Forward iterators
- Bidirectional iterators
- Random access iterators
- Output iterators
In your problem case the input iterators semantics fit. Specifically in input iterators operator*()
does not have to return a reference to an object it can even return the a newly created object. Thus avoiding having an "dummy" object inside the iterator object as Bjorn suggested.
You can view more here.
Since an iterator is a value object, why not just setting a member to the value you want to return, and return a reference to the member?
Short answer is, this will lead to undefined behaviour, you are after all returning a reference to a temporary! One option (if this iterator does not have to re-entrant is to have a class member (of type spVector3D) to which you "assign" the returned value (of course you could do it more optimally by passing in a reference to this to GetPoint as well as index), and then return that.
精彩评论