[C++] std::list swapping elements, how?

Started by
11 comments, last by Sharlin 16 years, 10 months ago
I am having a difficulty figuring out how to swap two items in a list. I have a list which holds pointers to an object. The object is rendered in the order it was inserted into the list. Now, based on some logic, I need to swap two items in the list so that their order changes when rendering. How can I do that? std::list<MyObject*> objs; objs.push_back(new MyObject("one")); objs.push_back(new MyObject("two")); objs.push_back(new MyObject("three")); objs.push_back(new MyObject("four")); objs.push_back(new MyObject("five")); Now, the list is in the order I pushed back the objects. But how can I swap MyObject pointer "five" with "three"? Any help would be greatly appreciated. Thank you all.
Advertisement
you could switch to a deque. but u can swap elements with a list too with two iterators.

list<int> mylist;
mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);
mylist.push_back(4);
mylist.push_back(5);

list<int>::iterator i = mylist.begin();
list<int>::iterator j = mylist.begin();
j++; j++; j++;
cout << (*i) << endl;
cout << (*j) << endl;
int temp = *i;
*i = *j;
*j = temp;
cout << (*i) << endl;
cout << (*j) << endl;
Same way you swap anything in C++, std::swap(*iteratorAtThree,*iteratorAtFive);

If the logic is some kind of sort operation that you will be applying to each element, make it perform like operator<() and write a functor for it:

struct DrawSorter {    bool operator()( const MyObject *one, const MyObject *two ) const {        return one->sortOrder < two->sortOrder;    }};objs.sort(DrawSorter());
How exactly is it that you come to know that two particular objects need to be swapped? What relates the two particular objects together? A comparison?
Is this some kind of sort or partial sort? It sounds like it is. If so, you're asking the wrong question, and should instead be asking how to sort the list (a higher level goal).
You may also be using the wrong container type.

What is the higher level goal here - Swapping helps achieve what?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
I am using a list to hold UI objects ( form, button, checkbox, etc ). The list is populated in the order that the objects are created. During rendering, I render the objects in the order they appear in the list. But, I need to introduce the functionality that when an object ( form 1 ) comes into focus, it is swapped with any other form within the list that is at the end of the list. This way, when the renderer draws the form 1, it is draw on top of any other forms that may have been drawn.
Here is the code in that function:

m_controls is the std::list that holds all the controls.
BringToFront is a function that all the controls have.

What I am trying to do is simply swap the control calling it (this) with whatever control is at the end of the list. I can not remove and push_back because this function is called within an iterator for the list.

void BringToFront(void){	std::list<TvControl*>::iterator from = this->m_form_manager->m_controls.end();	std::list<TvControl*>::iterator to = std::find(this->m_form_manager->m_controls.begin(), this->m_form_manager->m_controls.end(), this);	if ( (*from) != this )	{		TvControl* tmp;		tmp = *from;		from = to;		*to = tmp;	}}


This code breaks, compiles but gives: list iterator not dereferencable error in the if statement. I'm confused by the pointers here, anyone can help?
Quote:Original post by rip-off
Same way you swap anything in C++, std::swap(*iteratorAtThree,*iteratorAtFive);

If the logic is some kind of sort operation that you will be applying to each element, make it perform like operator<() and write a functor for it:

*** Source Snippet Removed ***


Or, since you are using iterators, std::iter_swap():


jfl.
Thanks jflanglois! I was looking in the wrong place. I have updated my function to this:

void TvControl::BringToFront(void){	std::list<TvControl*>::iterator from = std::find(                   this->m_form_manager->m_controls.begin(),                    this->m_form_manager->m_controls.end(),                    this->m_form_manager->m_controls.back());	std::list<TvControl*>::iterator to = std::find(                   this->m_form_manager->m_controls.begin(),                    this->m_form_manager->m_controls.end(),                    this);	std::iter_swap(from, to);}


and now it works as desired! Thank you all!
Quote:Original post by azherdev
Thanks jflanglois! I was looking in the wrong place. I have updated my function to this:

*** Source Snippet Removed ***

and now it works as desired! Thank you all!


Note that std::swap() would have worked fine as well. Your code was simply wrong because you were assigning iterators, not pointed-to elements.

Note also that you can simplify your code:

void TvControl::BringToFront(){  std::iter_swap(    std::find(      m_form_manager->m_controls.rbegin(),       m_form_manager->m_controls.rend(),       this ),    m_form_manager->m_controls.rbegin() );}


You don't need to explicitly use this for members. You might also consider making m_form_manager a non-pointer.

Also, don't use void to denote no parameters, that's a C construct.

Finally, I'm not too sure about controls having a reference to the container they're in, much less modifying their own position.


jfl.
Quote:Original post by azherdev
I am using a list to hold UI objects ( form, button, checkbox, etc ). The list is populated in the order that the objects are created. During rendering, I render the objects in the order they appear in the list. But, I need to introduce the functionality that when an object ( form 1 ) comes into focus, it is swapped with any other form within the list that is at the end of the list. This way, when the renderer draws the form 1, it is draw on top of any other forms that may have been drawn.
Ah cool, that's fine then. That's a perfectly valid reason. It still helps to explain more about what you're doing straight off though.[smile]

Given the operations you're performing on the list you might find that a vector is just as suitable, if not more.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement