Remove item from std :: list by reference

std::list<Reader> readers;

readers.push_back(Reader());

Reader& r = *(readers.begin());

/* at this point, the exact place in list, where the reader was picked out, is forgotten. 
   Only 'r' shows which element of the list it is. */

readers.erase(r); //<---how to do this?

      

Clients receive new instance reader objects from the dispatcher / dispatcher. The manager maintains an internal list of all sent and invalid / frees cached data if "all interested" raised it by watching the pool of sent readers.

When the client is no longer interested in the data, it must return the reader to the manager for removal from the pool. But I don’t want the client to keep the iterator β€” he had absolutely no interest in the manager guts and the reader pool; it only needs that own reader, not an iterator pointing to it. So, to remove it, it calls the manager's cleanup function, referencing that single reader.

Is there a better way to erase this reader from the list than to iterate over the entire list looking for that one reader that the link leads to?

+3


source to share


4 answers


Your parameters, if you only have an object reference, should use std::list::remove

readers.remove(r);

      

or std::find

in combination withstd::list::erase

readers.erase(std::find(readers.begin(), readers.end(), r));

      



The former should iterate over the entire list, while the latter will stop when it finds the first element and then remove it. For a large list, this can make a big difference.

Both of these options only work when items are unique. If you have unique elements, you can use std::find_if

and provide a functor that compares the address of the elements. This way you can ensure that you are only deleting the referenced object and not being compared to an equal.

readers.erase(std::find_if(readers.begin(), readers.end(), [&](const auto& e) {return &r == &e;}));

      

+3


source


Use std::remove

in conjunction witherase

readers.erase(std::remove(readers.begin(), readers.end(), r), readers.end());

      



Also, u cannot remove an item from the list by value without iterating over it. If you think about it, it doesn't even make sense, because the pointers inside the list must be updated .

+2


source


you can compare pointers to check if they are the same object

readers.remove_if([r=&r](auto& x){return &x==r;});

      

+2


source


If the list can contain equal values, you can do something like the following

#include <iostream>
#include <list>

int main()
{
    struct Reader { std::pair<char, int> p; };
    std::list<Reader> readers;

    readers.push_back({{ 'A', 1 } });
    readers.push_back({ { 'A', 2 } });
    Reader &rr = readers.back();
    readers.push_back({ { 'A', 3 } });

    readers.remove_if([&rr](const Reader &r) { return &r == &rr; });

    for (const auto &r : readers)
    {
        std::cout << r.p.first << ' ' << r.p.second << std::endl;
    }

    return 0;
}

      

Program output

A 1
A 3

      

+1


source







All Articles