2013-07-31 3 views
2

У меня есть простой класс, который я храню в векторе в качестве указателей. Я хочу использовать находку на векторе, но он не может найти мой объект. После отладки он, похоже, не вызывает оператор ==, который я предоставил. Я могу «видеть» объект в отладчике, чтобы я знал его там. В приведенном ниже коде даже используется копия первого элемента в списке, но все еще не выполняется. Единственное, что я могу сделать, это использовать MergeLine * mlt = LineList.begin(), который показывает мне, что он сравнивает объекты и вообще не использует мой оператор равенства.std :: find not using my defined == operator

class MergeLine { 
public: 
    std::string linename; 
    int StartIndex; 
    double StartValue; 
    double FidStart; 
    int Length; 

    bool operator < (const MergeLine &ml) const {return FidStart < ml.FidStart;} 
    bool operator == (const MergeLine &ml) const { 
     return linename.compare(ml.linename) == 0;}  
}; 

Class OtherClass{ 
public: 
    std::vector<MergeLine*>LineList; 
    std::vector<MergeLine*>::iterator LL_iter; 
    void DoSomething(std::string linename){ 
// this is the original version that returned LineList.end() 
// MergeLine * mlt 
// mlt->linename = linename; 

// this version doesn't work either (I thought it would for sure!) 
     MergeLine *mlt =new MergeLine(*LineList.front()); 
     LL_iter = std::find(LineList.begin(), LineList.end(), mlt); 
     if (LL_iter == LineList.end()) { 
     throw(Exception("line not found in LineList : " + mlt->linename)); 
     } 
     MergeLine * ml = *LL_iter; 

    } 
}; 

веселит, Марк

+5

Конечно, нет. 'a == b' не то же самое, что' * a == * b' ... –

+5

Указатели являются встроенными типами, поэтому они не используют перегруженный 'operator ==' –

+1

Любая конкретная причина, по которой вы сохранить в своих указателях вектора MergeLine вместо простых объектов MergeLine? Кроме того, не будет ли это более умным указателем, более подходящим для ваших нужд? – Antonio

ответ

2

Поскольку ваш контейнер содержит указатели, а не объекты, то сравнение будет между указателями. Единственный способ, которым указатели будут равны, - это когда они указывают на тот же самый объект. Как вы заметили, оператор сравнения для самих объектов никогда не будет вызван.

Вы можете использовать std::find_if и передать ему объект сравнения.

class MergeLineCompare 
{ 
    MergeLine * m_p; 
public: 
    MergeLineCompare(MergeLine * p) : m_p(p) 
    { 
    } 
    bool operator()(MergeLine * p) 
    { 
     return *p == *m_p; 
    } 
}; 

LL_iter = std::find_if(LineList.begin(), LineList.end(), MergeLineCompare(mlt)); 
+0

Отличный пример. Спасибо. – marcp

1

Я думаю, что вы действительно хотите использовать std::find_if так:

struct MergeLineNameCompare 
{ 
    std::string seachname; 

    MergeLineNameComp(const std::string &name) : seachname(name) 
    { 
    } 

    bool operator()(const MergeLine * line) 
    { 
     return seachname.compare(line->linename) == 0; 
    } 
}; 

LL_iter = std::find_if(LineList.begin(), LineList.end(), MergeLineNameCompare(linename)); 

operator == (независимо от формы которым) лучше сохраняются для реального сравнения равенства.

+0

Ваш ответ правильный, но Марк легче понять. Благодарю. – marcp

+0

Да, к сожалению, ответ @ mark-ransom не совсем правильный. – Clemens

+0

как это? Кажется, это работает. – marcp

0

Перегрузка оператора не может работать с указателями, поскольку она неоднозначна.

Бьерн Страуструп: -

Список литературы были введены в первую очередь для поддержки перегрузки операторов. C передает каждый аргумент функции по значению, и если передача объекта по значению будет неэффективной или неуместной, пользователь может передать указатель . Эта стратегия не работает, когда используется перегрузка оператора . В этом случае заметное удобство существенно, так что пользователь не может вставлять адреса операторов, если объекты имеют размер .

Таким образом, может быть не лучше, но все-таки: -

std::vector<MergeLine>LineList; 
    std::vector<MergeLine>::iterator LL_iter;