Boost Intrusive Swap

468 views Asked by At

I have a class declared as class MyClass : public list_base_hook<link_mode<normal_link>>. I also have a list declared as list<MyClass> global_list_MyClass.

I insert 10 nodes into global_list_MyClass using a for loop. My objective is try to swap Node1 and Node2 using boost::intrusive::swap but seems like failed (a lot of compilation error).

I tried to search around internet but can't find any good example for this.

Example code:

class MyClass : public list_base_hook<link_mode<normal_link>>
{
public:
   int nValue;

public:
    MyClass(){}
    virtual ~MyClass(){}
};
static boost::intrusive::list<MyClass> global_list_MyClass;


//Insert 10 nodes
for (int n=0; n<10; n++)
{
  MyClass *p_oTMP1 = new MyClass();
  p_oTMP1->nValue = n;
  global_list_MyClass.push_back(*p_oTMP1);
}


//Search for Target node 1
int nTarget1 = 5;
boost::intrusive::list<MyClass>::iterator oTmpTarget1;
for (list<MyClass>::iterator iTmpToken=global_list_MyClass.begin();     iTmpToken!=global_list_MyClass.end(); iTmpToken++)
{
  if (!(iTmpToken->nValue == nTarget1))
    continue;
  oTmpTarget1 = iTmpToken;
  break;
}


//Search for Target node 2
int nTarget2 = 6;
boost::intrusive::list<MyClass>::iterator oTmpTarget2;
for (list<MyClass>::iterator iTmpToken=global_list_MyClass.begin(); iTmpToken!=global_list_MyClass.end(); iTmpToken++)
{
  if (!(iTmpToken->nValue == nTarget2))
    continue;
  oTmpTarget2 = iTmpToken;
  break;
}


//Swap Node1 with Node2
/*Here is what i not sure what to do with boost::intrusive::swap or     global_list_MyClass.swap()
1

There are 1 answers

6
Angew is no longer proud of SO On BEST ANSWER

I don't think you can use swap() here - that's for swapping containers, not nodes within containers. You can remove the elements and re-insert them at the swapped locations, though:

void swapItems(boost::intrusive::list<MyClass> &list, boost::intrusive::list<MyClass>::iterator it1, boost::intrusive::list<MyClass>::iterator it2)
{
  if (it1 == it2) return;
  MyClass &node1 = *it1;
  MyClass &node2 = *it2;
  it1 = list.erase(it1);
  if (it1 == it2) {  //1 was immediately followed by 2
    list.insert(++it2, node1);
    return;
  }
  it2 = list.erase(it2);
  list.insert(it2, node1);
  list.insert(it1, *node2);
}

Of course, writing this function as tailored to MyClass is almost absurd - it would be much better served as a function template to work with an arbitrary class. It could perhaps even templated by container type, but you'd have to be more careful there with regard to iterator invalidation.

An alternative would be to provide something like a swapValues() function in your class anc call that:

void MyClass:swapValues(MyClass &other)
{
  using std::swap;
  swap(nValue, other.nvalue);
  //dtto for other members, but NOT for the boost::intrusive linking structure
}