views:

1544

answers:

4

I want to find in a vector of Object pointers for a matching object. Here's a sample code to illustrate my problem:

class A {
public:
    A(string a):_a(a) {}
    bool operator==(const A& p) {
        return p._a == _a; 
    }

private: 
    string _a;
};

vector<A*> va;

va.push_back(new A("one"));
va.push_back(new A("two"));
va.push_back(new A("three"));

find(va.begin(), va.end(), new A("two"));

I want to find the second item pushed into the vector. But since vector is defined as a pointers collection, C++ does not use my overloaded operator, but uses implicit pointer comparison. What is the preferred C++-way of solutiono in this situation?

A: 

Try using find_if instead. It has a parameter for a predicate where you can decide exactly how to check wheter you found the right element.

http://www.sgi.com/tech/stl/find_if.html

Laserallan
+8  A: 

Use find_if with a functor:

template <typename T>
struct pointer_values_equal
{
    const T* to_find;

    bool operator()(const T* other) const
    {
        return *to_find == *other;
    }
};


// usage:
void test(const vector<A*>& va)
{
    A* to_find = new A("two");
    pointer_values_equal<A> eq = { to_find };
    find_if(va.begin(), va.end(), eq);
    // don't forget to delete A!
}

Note: your operator== for A ought to be const, or, better still, write it as a non-member friend function.

James Hopkin
I think it must be find_if in the code?
esrkan
Indeed - you can only std::find() a predicate in a container of predicates!
MSalters
james can you add some more explanation abt this line pointer_values_equal<A> eq = { to_find };
yesraaj
yesraaj: pointer_values_equal is an aggregate (no private data, bases, virtual functions, constructors), so it can be initialised using {} (array-style) initialisation.
James Hopkin
+4  A: 

Either use std::find_if and provide a suitable predicate yourself, see other answers for an example of this.

Or as an alternative have a look at boost::ptr_vector, which provides transparent reference access to elements which are really stored as pointers (as an extra bonus, memory management is handled for you as well)

Pieter
+1  A: 

You could also use Boost::Lambda:

using namespace boost::lambda;
find_if(va.begin(), va.end(), *_1 == A("two"));

Of course, you should prefer to use shared_ptrs so you don't have to remember to delete!

MattyT