web-dev-qa-db-ja.com

std :: find_ifにラムダを使用する方法

Std :: find_ifを使用して、いくつかの基準に一致するオブジェクトを見つけようとしています。以下を検討してください。

struct MyStruct         
{
    MyStruct(const int & id) : m_id(id) {}                      
    int m_id;
};
...         
std::vector<MyStruct> myVector; //... assume it contains things

MyStruct toFind(1);
std::vector<MyStruct>::iterator i = std::find_if(myVector.begin(), myVector.end(), ???);

???に何を入れるかわかりません

私が見たすべての例には、ハードコードされた値を使用してIDをチェックするラムダがあります。私が欲しいのは、toFindのIDがベクター内のいずれかのアイテムのIDと一致する場合にのみ、イテレーター/成功を返すことです。

私が見たすべての例は、2つのパラメーターを渡す方法を示していません

編集

追加情報2つの異なるシナリオがあります。構造体に==演算子がある場合と構造体に演算子==がない場合の2つです。このシナリオの一致を見つけることは、等価演算子に使用されるほど厳密ではありません。

(そして、答えてくれたすべての人に感謝します。私はあるケースでfind()を使用することができ、あなたの助けを借りて他のケースでfind_if()を使用することができました)

9
Tim

これを試して:

std::find_if(
    myVector.begin(), myVector.end(),
    [&toFind](const MyStruct& x) { return x.m_id == toFind.m_id;});

または、MyStructに適切な==オーバーロードを定義している場合は、findを使用できます。

std::find(myVector.begin(), myVector.end(), toFind);  // requires ==

find_ifバージョンは通常、ある種のheterogeneousルックアップがある場合に最適です。たとえば、intの値ではなく、MyStructが指定された場合などです。

8
Kerrek SB

これがラムダキャプチャの出番です。ラムダに渡されるパラメーターのタイプを指定する以外に、ラムダを作成するために使用される既存の変数を指定することもできます。したがって、この場合は次のようになります

_std::vector<MyStruct>::iterator i = std::find_if(myVector.begin(),
    myVector.end(), 
    [&](const auto& val){ return val.m_id == toFind.m_id; } );
_

したがって、_[&]_は、参照によってラムダの本体で使用されるすべての変数をキャプチャすることを示しています。 _(const auto& val)_は、ラムダのoperator()をテンプレートにして、任意の型を取り込めるようにします。次に、本文で_find_if_からtoFindに渡されるものを比較します。

4
NathanOliver

次のものを使用できます。

MyStruct toFind(1);
std::vector<MyStruct>::iterator i =
    std::find_if(myVector.begin(), myVector.end(),
                 [&](const auto& e) { return e.id == toFind.id; });
1
Jarod42

次のようにしてください:

std::find_if(myVector.begin(), myVector.end(), 
          [&toFind] (const auto &ele) { return ele.m_id == toFind.m_id}; );
0
Steephen