31

I am trying to use std::find_if to find an object that matches some criteria. Consider the following:

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(), ???); 

I am not sure what to put in the ???

All the examples I have seen have a lambda that uses a hard-coded value to check for the ID. What I want is to return the iterator/success only if the id of toFind matches the id of one of the items in the vector.

All the examples I have see don't show me how to pass the two parameters

EDIT

Additional info There are two different scenarios I have to use this for One in which there is an == operator for the struct and another in which there is no operator == for the struct - and i can't create one because the criteria for finding a match for this scenario is not as rigid as would be used for an equivalence operator.

(And thanks to all who responded; I was able to use find() in one case and with your help was able to use find_if() for the other)

4 Answers 4

53

Try this:

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

Alternatively, if you had defined an appropriate == overload for MyStruct, you could just use find:

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

The find_if version is usually best when you have some kind of heterogeneous lookup, for example if you were just given an int, not a value of MyStruct.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks - in one case I had a struct that provides == operator.
@Tim: The operator can also be provided as a free function or as a friend function.
thanks, yes, I know, but this is in a codebase where I am trying to tread as lightly as I can on the existing code
More importantly - the criteria I want for finding the id match is NOT the same as the criteria I would use for equivalence for this object type
@Tim: Yes, then a lambda, or even a suitably named functor class, is the way to go.
11

This is where the lambda capture comes into play. Besides saying what type of parameters are to be passed to the lambda you can also say what existing variables are to be used to construct the lambda with. So in this case you would have something like

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

So the [&] says capture all variables used in the body of the lambda by reference. The (const auto& val) makes the operator() of the lambda a template and lets you take in any type. Then in the body we compare what is passed in from find_if to toFind.

Comments

1

You may use the following:

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

Comments

1

Do as following:

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

1 Comment

I would suggest explicitely capturing toFind in the capture list

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.