web-dev-qa-db-ja.com

カスタムクラスオブジェクトのベクトルでstd :: find / std :: find_ifを使用する方法?

Nickという名前のユーザーを表すクラスがあり、その上で_std::find_if_を使用します。ここで、ユーザーリストベクトルに、渡した同じユーザー名のオブジェクトが含まれているかどうかを確認します。ユーザー名に対して新しいNickオブジェクトを作成するには、テストして_== operator_をオーバーロードし、オブジェクトで_find/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_をオーバーロードしたので、Nick == 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);
    };
};
_
26
Speed

クラス外の2つのオブジェクトで、メンバーではなくツール関数としてoperator ==を定義する必要があります。

それから、それを友達にするために、関数の宣言をクラス内に置くだけです。

次のようなものを試してください:

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) );

「新規」の必要はありません。

16
Nikko

C++ 0Xを使用している場合は、単純なラムダ式を使用できます

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

私はあなたが==演算子をオーバーロードしたかったのを知っていますが、同じことは述語で簡単にできます:

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では、ラムダ式を使用して同じことをより簡潔に行えることに注意してください。

9
Seb Holzapfel

Find関数へのポインターを渡しています。新しいドロップ:

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

また、演算子はconst参照によって引数を受け入れる必要があり、変更しません。

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

この方法で、あるコンストラクターから別のコンストラクターを呼び出そうとしていることに気付きました。

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

申し訳ありませんが、これは機能しません。行Nick()は一時的なものを作成するだけで、thisには影響しません。コンストラクター転送は、C++ 0x(今後の標準)でのみ可能です

あなたの問題に関しては、この質問は数日前にbinary_searchが同じ根拠をカバーしていることを尋ねました。一番の答えは最高です。

std :: binary_searchの神秘的な制限

HTH。

追伸これはコメントであるのが理想ですが、あまりにも冗長です

1
Armen Tsirunyan

Boost :: bindを使用できます

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

bool Nick :: 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;
}
0
Nelstaar