Accessing the previous and next elements through a std::list iterator

closed account (D80DSL3A)
Is there a simple way to get iterators to the elements on either side of that pointed to (?) by a std::list iterator ?

I recently did this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  std::list<T> LT;
// populate the list
// one data member of T depends on the values of data members of the elements on either side in the list.

std::list<T>::iterator it = LT.begin();
while( it != LT.end() )
{
    int x1=0, x2=0;// default values for the "values from either side"
    if( it != LT.begin() )
    {
        std::list<T>::iterator itPrev = it;
        --itPrev;
        x1 = itPrev->x;// finally!
    }

    // similar code for obtaining x2 from an itNext

    it->F = f(it->x, x1, x2);// the end need
}


I looked at this sites documentation for std::list
http://www.cplusplus.com/reference/iterator/BidirectionalIterator/
and found no method for getting an iterator to the previous or next elements.

Something like it.prev() would be nice, so that in place of lines 9-14 above, I may write:
if( it.prev() ) x1 = it.prev()->x;// as with a "hand rolled" list.

Is there a method for doing this?
How may the working method above be simplified?

Thank you.

EDIT: corrections to lines 12,13 and code comments.
Last edited on
closed account (D80DSL3A)
Thanks.
Another C++11 only feature, eh?
I guess the language did need an overhaul.

How does one test that the returned iterator is valid?

This may seem boneheaded, but I'm trying to see the beauty of the STL here.
Another C++11 only feature, eh?
I guess the language did need an overhaul.

You could accomplish the same thing prior to C++11 using std::advance. The next/prev notation is really a matter of convenience.


How does one test that the returned iterator is valid?

In both cases, one should know the iterator will be valid before using the functions. There is no way to test the returned iterator in general. Of course, if you're using next to advance one element at a time, you may compare it to the end iterator of the container. There isn't a convenient value to test against if you're using prev analogously. (One would need to ensure it didn't compare equal to the begin iterator of the container before invoking prev.)

[edit: std::distance is useful in the case of advancing in either direction more than one element.]
Last edited on
closed account (D80DSL3A)
cire wrote:
In both cases, one should know the iterator will be valid before using the functions. There is no way to test the returned iterator in general.

Thank you. That's how I thought it worked. I just wanted to make sure I wasn't missing some tool for working with adjacent elements in a list.

I'll chalk the difficulty up to the use case, for which std::list was probably not intended ("I'm just a container, man!").

EDIT:
So, what I'm doing here is necessary:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
std::list<T>::iterator itPrev, itCurr, itNext;
itCurr = L.begin();

while( itCurr != L.end() )// itCurr is always valid within this while loop
{
    // check against begin() 1st
    if( itCurr != L.begin() )// there is a valid previous element
    {
        itPrev = itCurr; --itPrev;// copy, then decrement
        // use itPrev
    }

    
    itNext = itCurr;// we know itCurr != L.end()
    if( ++itNext != L.end() )// so it's OK to increment then compare here
    {
        // use itNext
    }

    ++itCurr;
}
Last edited on
Topic archived. No new replies allowed.