I have a list of pointers to objects where some of the objects contain a pointer to another object. When I remove an object in the list which has a linked object I need to remove them BOTH. I also want to position the next iterator at a convenient position which will usually be just after the object in the list which is to be deleted. Or if the linked item is next it will have to be just after the linked item.
There are peripheral issues such as why not using smart pointers etc. But this is just a simple demo - so please ignore lifecycle issues. I am looking for comments on the RemoveAllAssociated function.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class A
{
public:
A(int timestamp) : m_timestamp(timestamp), m_red(false), m_linkedmsg(0) {}
virtual ~A() {}
int gettimestamp() const { return m_timestamp; }
A* getLinkedMsg() const { return m_linkedmsg; }
void setLinkedMsg(A* linked) { m_linkedmsg = linked; }
bool IsRed() const { return m_red; }
void setRed(bool col = true) { m_red = col; }
protected:
int m_timestamp;
bool m_red;
A* m_linkedmsg;
};
class B : public A
{
public:
B(int timestamp) : A(timestamp) { setRed(true); }
virtual ~B() {}
};
//erase item and linked iterator if available and return next iterator
std::list<A*>::iterator RemoveAllAssociated(std::list<A*>& thelist, A* item) {
std::list<A*>::iterator it = find(thelist.begin(), thelist.end(), item);
if(it != thelist.end()) {
cout << "found original item in list with timestamp=" << (*it)->gettimestamp() << "\n";
//we now want to delete linked as well as original
//first delete linked
A* linked = (*it)->getLinkedMsg();
std::list<A*>::iterator found_it = find(thelist.begin(), thelist.end(), linked);
if(found_it != thelist.end()) {
cout << "found linked item with timestamp=" << (*found_it)->gettimestamp() << "\n";
delete *found_it;
std::list<A*>::iterator after_linked_it = thelist.erase(found_it);
}
//now erase item in list
//Need to return next iterator. Usually will be just after item
//check a valid iterator returned
//We want iterator to be positioned either just after
delete *it; //or could have done: delete item;
return thelist.erase(it);
} else
cout << "original item not found in list\n";
return thelist.end();
}
int main() {
A* a1 = new B(0);
A* a2 = new B(1);
A* a3 = new B(2);
A* a4 = new B(3);
A* a5 = new B(4);
A* a6 = new B(5);
a2->setLinkedMsg(a1);
//put them in a list
std::list<A*> alist;
alist.push_back(a5);
alist.push_back(a6);
alist.push_back(a1);
alist.push_back(a2);
alist.push_back(a3);
alist.push_back(a4);
std::list<A*>::iterator it = RemoveAllAssociated(alist, a2);
if(it != alist.end())
cout << "next item in list is " << (*it)->gettimestamp() << endl;
//print out what is left to check correct items erased
for(it = alist.begin(); it != alist.end(); ++it) {
cout << "address=" << *it << " ts=" << (*it)->gettimestamp() << endl;
}
//cleanup
it = alist.begin();
while(it != alist.end()) {
delete *it;
it = alist.erase(it);
}
return 0;
}