How can I erase elements from a boost::intrusive::list
while iterating through it? The following code fails with an assertion failure https://wandbox.org/permlink/nzFshFSsaIrvBiTa
#include <iostream>
#include <vector>
#include <boost/intrusive/list.hpp>
using std::cout;
using std::endl;
class Integer : public boost::intrusive::list_base_hook<> {
public:
explicit Integer(int a_in) : a{a_in} {}
int a;
};
int main() {
auto vec = std::vector<Integer>{};
vec.push_back(Integer{1});
vec.push_back(Integer{2});
vec.push_back(Integer{3});
auto list = boost::intrusive::list<Integer>{};
for (auto ele : vec) {
list.push_back(ele);
}
for (auto it = list.begin(); it != list.end();) {
if (it->a == 2) {
it = list.erase(it);
} else {
++it;
}
}
for (auto ele : list) {
cout << ele.a << endl;
}
}
Your problem is that you have pushed temporaries into the list:
You probably meant to write:
This is classic confusion when starting to work with intrusive containers: nothing is by value like all the with all the standard library containers.
To avoid situations like this, consider using the auto-unlinking hook mode.
Demo
Even safer than having to think about reference-qualifying the loop variable, is having no loop at all:
Live On Coliru
Prints
With
auto_unlink
:With that in place, even adding
will correctly unlink the corresponding node from the intrusive list:
Live On Coliru
Prints