Ricko M
Ricko M

Reputation: 1784

Vector find with pointers of custom class

I am trying to understand operators you need to overload when working with custom classes in STL(SCL).

Can any one please tell me what is it I am doing wrong ?

class myClass
{
public:
    int data;
    myClass()
    {
        data =0;
        cout<<"Default const "<<endl;
    }

    myClass(int x)
    {
        data = x;
        cout<<"Int constructor"<<endl;
    }

    myClass(const myClass &m)
    {
        cout<<"Copy constructor"<<endl;
    }

    bool operator == (const myClass &temp)
    {
        cout<<"Operator called &";
        return data == temp.data;
    }

    bool operator == (const myClass *temp)
    {
        cout<<"Operator called *";
        return data == temp->data;
    }
};

int main ()
{
    /*
    vector<int> myvector;
    myvector.push_back(10);
    myvector.push_back(20);
    myvector.push_back(30);

    cout << "myvector contains:";
    for_each (myvector.begin(), myvector.end(), meObj);
    */

    vector<myClass*> myVec;
    myClass temp;
    myVec.push_back(&temp);
    myClass temp2(19);
    myVec.push_back(&temp2);
    myClass temp3(19);

    vector<myClass*>::iterator it = find(myVec.begin(),myVec.end(),&temp2); //works
    if(it!=myVec.end())
    {
        cout<<"Value is "<<(*it)->data;
    }

    vector<myClass*>::iterator dit = find(myVec.begin(),myVec.end(),&temp3); //fails
    if(dit!=myVec.end())
    {
        cout<<"Value is "<<(*dit)->data;
    } 

    cout << endl;

    return 0;
}

Please correct me if I am wrong, but the first find works as it does a address comparison. What do I need to overload for the above to work ?

Do both the signature make sense ?

bool operator == (const myClass &temp); // seen in many places
bool operator == (const myClass *temp); // what if two pointer types of same object are being compared?

Cheers!

Upvotes: 3

Views: 3253

Answers (3)

James Kanze
James Kanze

Reputation: 154047

What do you mean by "work" in this case? Generally, when you're storing pointers, it's because the objects do have identity, and comparing the address is the correct thing to do. Otherwise, you should probably be storing values (although there are exceptions). Anyway, you can always use find_if, and any comparison criteria you want. For anything but the simplest types, I find myself using find_if more often than find anyway; usually, you're not looking for equality, but rather for some specific type of match. Here, for example, you'd more likely want something like:

std::vector<MyClass>::iterator it = std::find_if( myVect.begin(), myVect.end(),
                                                  boost::bind(&MyClass::id, _1, 19) );

(Supposing that the data here is some sort of identifier, and that you've provided a member function, myClass::id() to read it.)

Upvotes: 0

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272802

Operator overloads must have at least one user-defined type. So you cannot overload operator== for two pointers, for instance.

Your myClass::operator==(const myClass *temp) is valid in the sense that it compiles, but makes very little semantic sense, and is not recommended (there are very few situations where you'd want to do T x; T *y; ... (x == y)).

For your situation, where you have a vector of pointers, you may want to consider std::find_if, which takes a predicate. Something like:

class CompareByPointer
{
public:
    explicit CompareByPointer(const myClass &p) : p(p) {}
    bool operator() (const myClass &rhs) const { return p->data == rhs->data; }
private:
    const myClass &p;
};

...

find_if(myVec.begin(), myVec.end(), CompareByPointer(&temp2));

[As a side note, you should generally define member functions const wherever possible. So your operator overloads should be const.]

Upvotes: 4

yasouser
yasouser

Reputation: 5187

In the sample code, you haven't pushed &temp3 into myVec. So it makes sense for the second std::find to fail.

Upvotes: 1

Related Questions