Boost Pointer Container Library

From Schmid.wiki
Jump to: navigation, search

Find Element by Address

Problem

Removing or just finding a member in a ptr_list by address is not immediately possible:

boost::ptr_list<int> l;
int *a = new int(7);
int *b = new int(7);
l.push_back(a);
l.push_back(b);

// The obvious thing to try is remove, which doesn't compile:
// l.remove(a); // error
// l.remove(*a); // error

// The following compiles, but searches using int::operator==
// instead of pointer equality, which results in finding a and not b.
boost::ptr_list<int>::iterator it = find(l.begin(), l.end(), *b);
l.erase(it); // erase a

Obviously, if the contained type doesn't have operator==, it doesn't even compile:

struct A {};
boost::ptr_list<A> l;
A *a = new A;
l.push_back(a);
// Doesn't compile, because A has no operator==
// boost::ptr_list<A>::iterator it = find(l.begin(), l.end(), *a); // error

Solution

Define a new algorithm that searches using pointer equality:

// Returns an iterator pointing to the first element of pointer container that has the same
// address as ptr.
// For some mind-boggling reason, neither ptr_list<A>::remove(A *ptr)
// or find(begin, end, A *ptr) works with ptr_list.
template<
    typename Ptr_container_iterator,
    typename Value_type
>
Ptr_container_iterator find_ptr(
    Ptr_container_iterator begin, Ptr_container_iterator end,
    Value_type *ptr) {

    Ptr_container_iterator i;
    for(i = begin; i != end; ++i) {
        if(&(*i) == ptr) break; // compare by address
    }
    return i;
}

And use it:

struct A {};
boost::ptr_list<A> l;
A *a = new A;
l.push_back(a);
boost::ptr_list<A>::iterator it = find_ptr(l.begin(), l.end(), *a);
l.erase(it);
Personal tools