0

There are a few posts around iterators with lists here using the insert and splice here functions but I am still not able to translate them for my case, I am iterating across a list and if a condition is meet I want to splice (move) the element to another list, but as stated here the iterator jumps to the splices container. How can I keep the iterator related to the original loop as in the example below.

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <ctime>
#include <list>

using namespace std;

class Individual {
  public:
    Individual(bool state) : state_(state) {}
    bool my_state(void) {
        return state_;
    }
  private:
    bool state_ = true;
};


int main () {
    cout << "----------Enter Main----------" << endl;
    list<Individual>  list_individuals;
    list<Individual>  cache_list_individuals; 

    // initialise
    for (auto i = 0; i < 100; ++i) {
        if (i <= 50)
            list_individuals.push_back(new Individual(true));
        else
            list_individuals.push_back(new Individual(false));
    }
    unsigned counter = 0;
    for (auto iter = list_individuals.begin(); iter != list_individuals.end(); ++iter, ++counter) {
        if ((*iter).my_state()) {
            cache_list_individuals.splice(cache_list_individuals.begin(),list_individuals, iter);
            // I need to make the iterator related to list_individuals not cache_list_individuals
        }
    }

    cout << "----------Exit Main----------" << endl;
    system("PAUSE");
    return 0;
}
Cyrillm_44
  • 701
  • 3
  • 17
  • 3
    Get the next iterator (still pointing into the first list) before you splice. – BoBTFish Jul 11 '18 at 06:14
  • 1
    Which would most easily be done changing your 2nd `for` to a `while` declaring a 2nd `iter_tmp` and either using `std::advance` or `std::next` (C++11) and assign `iter_tmp = iter;` before calling `advance` or `next` on `iter` and using `iter_tmp` to `splice`. – David C. Rankin Jul 11 '18 at 06:55
  • Iterators point to elements. You move an element, the iterator moves with it. If you want an iterator that doesn't move, make it point it to an element that doesn't move. – n. m. could be an AI Dec 13 '18 at 15:14

2 Answers2

1
for (iter = list.begin(); iter != list.end();) {
    otherIter = iter++;
    if (condition) {
        otherList.splice(otherList.cend(), otherIter, list);
    }
}

Move incrementing the iterator into the loop. Using a post increment, moves iter, and keeps it iterating through list, while otherIter is iterating through otherList after the splice().

-1

You could use a copy of your loop iterator to do the splicing:

if ((*iter).my_state()) {
    auto splice_iter = iter;
    cache_list_individuals.splice(cache_list_individuals.begin(), list_individuals, splice_iter);
}

But after copy both iterators will point to the moved element in the cache_list_individuals list.

David C. Rankin's comment above is where my code was trying to go.

miken32
  • 42,008
  • 16
  • 111
  • 154
Justsalt
  • 1,886
  • 3
  • 17
  • 24