2011-08-04 76 views
24

我有代表一個名爲Nick用戶類,我想用就可以std::find_if,在這裏我想找到如果用戶列表載體具有包含相同的用戶名我傳遞的對象。我試圖創建做了一些嘗試新Nick對象我要測試的用戶名和超載== operator,然後試圖在對象上使用find/find_if如何使用std :: find/std :: find_if與自定義類對象的向量?

std::vector<Nick> userlist; 
    std::string username = "Nicholas"; 

if (std::find(userlist.begin(), userlist.end(), new Nick(username, false)) != userlist.end())) { 
    std::cout << "found"; 
} 

我已經超載了== operator所以比較尼克== Nick2應該可行,但在函數返回error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Nick' (or there is no acceptable conversion)

這裏是我尼克類以供參考:

class Nick { 
private: 
    Nick() { 
     username = interest = email = ""; 
        is_op = false; 
    }; 
public: 
    std::string username; 
    std::string interest; 
    std::string email; 
    bool is_op; 

    Nick(std::string d_username, std::string d_interest, std::string d_email, bool d_is_op) { 
     Nick(); 
     username = d_username; 
     interest = d_interest; 
     email = d_email; 
     is_op = d_is_op; 
    }; 
    Nick(std::string d_username, bool d_is_op) { 
     Nick(); 
     username = d_username; 
     is_op = d_is_op; 
    }; 
    friend bool operator== (Nick &n1, Nick &n2) { 
     return (n1.username == n2.username); 
    }; 
    friend bool operator!= (Nick &n1, Nick &n2) { 
     return !(n1 == n2); 
    }; 
}; 

回答

14

你必須定義運算符==類的外部兩個對象作爲一種工具的功能,而不是一個成員。

然後讓它朋友只是寫在類中的函數的聲明。

嘗試這樣:

class Nick { 

public: 
    friend bool operator== (const Nick &n1, const Nick &n2); 
}; 


bool operator== (const Nick &n1, const Nick &n2) 
{ 
     return n1.username == n2.username; 
} 

而且你發現應該是這樣的:

std::find(userlist.begin(), userlist.end(), Nick(username, false)); 

沒有必要的 「新」。

+0

實際上,而不是定義一個朋友函數,你應該使用成員函數bool operator ==(const Nick&a)。 –

+1

你有選擇,但有很多程序員喜歡避免成員,如果不需要,並有運營商喜歡==作爲外部免費的朋友功能。我認爲這也是標準庫實現的情況。 – Nikko

+0

剛剛按照你的建議嘗試過。答案不應該是這樣的:'std :: find(userlist.begin(),userlist.end(),&Nick(username,false));'? – Marschal

3

你傳入的指針查找功能。刪除新的:

std::find(userlist.begin(), userlist.end(), Nick(username, false)) 

另外,您的運算符應該通過const引用來接受它們的參數,它們不會修改它們。

bool operator== (const Nick &n1, const Nick &n2) 
0

您可以使用boost ::綁定

std::find_if(userlist.begin(), userlist.end(), 
      boost::bind(& Nick::isFound, 
         _1)); 

只實現布爾尼克:: isFound()

您也可以通過標準

std::find_if(userlist.begin(), userlist.end(), 
       boost::bind(& Nick::compare, 
          _1, 
          nick)); 

實施

bool Nick::compare(const Nick & nick) 
{ 
    return this->username == nick.username; 
} 
1

我注意到你正在試圖從另一個調用一個構造函數以這種方式:

Nick(std::string d_username, bool d_is_op) { 
     Nick(); 
... 

嗯,對不起,但這不起作用。該生產線Nick()只是創建一個臨時的,不會影響this。構造函數轉發是唯一可能的C++ 0x中(即將推出的標準)

至於你的問題 - 這個問題問前兩天約binary_search涵蓋了同樣的理由。最好的答案是真棒。

Mystical restriction on std::binary_search

HTH。

P.S.理想情況下這應該是一個評論,但它只是太冗長

36

如果您正在使用的C++ 0x,你可以使用一個簡單的lambda表達式

std::string username = "Nicholas";  
std::find_if(userlist.begin(), userlist.end(), [username](Nick const& n){ 
    return n.username == username; 
}) 
+7

他沒有說他使用C++ 0X ... – Nikko

+13

@Nikko他也不會說他不是。因此,在這個答案的開頭,這個詞「如果」。 –

+0

是的,這一切都在2011年做出了某種感覺,也許在我的評論後有一個編輯... – Nikko

9

我知道你想重載==運營商,但同樣的事情可以很容易地斷言完成:

struct UsernameIs { 
    UsernameIs(string s) : toFind(s) { } 
    bool operator() (const Nick &n) 
     { return n.username == toFind; } 
    string toFind; 
}; 

int main() 
{ 
    vector<Nick> vn(10); 
    string nameToFind = "something"; 
    find_if(vn.begin(), vn.end(), UsernameIs(nameToFind)); 
} 

請注意,在C++ 0x中,可以更簡潔地對lambda表達式做同樣的事情。

+0

我得到'錯誤:功能UsernameIs'沒有匹配。可能是什麼問題? – Sitesh