开发者

STL iterator: "dereferencing" iterator to a temporary. Is it possible?

开发者 https://www.devze.com 2023-01-23 03:05 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消