How can I move an item from a C ++ 11 container to the end of the container?

How do I move an element from a C ++ 11 container to the end of the container?

I use a list on purpose, but I can use a vector if needed (or perhaps any container, it would be useful to get generic container solutions).

I have a list of items. I have value. I pass this value to each element; one of them will answer. The first one that answers I want to move to the end of the container.

My existing code looks like this:

std::list<elements> m_elements
...
bool handle(event e)
{
    for(auto &element : m_elements)
    {
        if(element->handle())
            return true;
    }
    return false;
}

      

But now I want to move the element handle()

to the end m_elements

. For a little context, I'm working on a GUI windowing system. Thus, whatever the window is, to grab the mouse, you have to jump up when drawn; windows in m_elements

are displayed one by one (so the last item is on top).

It might be worth noting that std::shared_ptr

s.

EDIT

In case anyone comes across this question and answers a similar situation.

I actually needed to iterate back through my container to handle the input, because the last item is drawn last, i.e. it's on top, so it must be the first element to try to intercept the input.

It was easy to do. However, splicing the reverse iterator to the end of your container is a little trickier. std::reverse_iterator.base()

returns you an Iterator NEXT if the iterator was a forwarding iterator, so you need an std::advance

iterator -1

to successfully move the actual element that is being "intercepted".

for(auto itr = m_elements.rbegin(); itr != m_elements.rend(); ++itr)
{
    if((*itr)->handle(e))
    {
        auto itr2 = itr.base();
        std::advance(itr2,-1);
        m_elements.splice(m_elements.end(), m_elements, itr2);
        return true;
    }
}

      

Hope this helps the next poor soul.

+3


source to share


1 answer


If you want to remove an element and add it to the end (effectively shifting everything else), you can do so using a method std::list::splice

that will reconnect a node at a new location without requiring any nodes to be created or destroyed. All it will do is adjust the node pointers to existing nodes to reflect the change you want.

for (auto i = m_elements.begin(); i != m_elements.end(); ++i) {
    if ((*i)->handle()) {
        // Move this node to the back.
        m_elements.splice(m_elements.end(), m_elements, i);

        return true;
    }
}

return false;

      



There are more general solutions that will apply to any container (including std::list

), but they may be suboptimal when compared to the technique for that particular container.

+8


source







All Articles