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

This topic is 4054 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

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.

Share on other sites
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;

Share on other sites
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());

Share on other sites
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?

Share on other sites
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.

Share on other sites
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?

Share on other sites
Quote:
 Original post by rip-offSame 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.

Share on other sites
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!

Share on other sites
Quote:
 Original post by azherdevThanks 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.

Share on other sites
Quote:
 Original post by azherdevI 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.

1. 1
2. 2
Rutin
20
3. 3
JoeJ
17
4. 4
5. 5

• 37
• 23
• 13
• 13
• 17
• Forum Statistics

• Total Topics
631704
• Total Posts
3001822
×