find in a vector<someclass>

Hi, I am having the hardest time getting my head wrapped around how find works.

in the find reference http://www.cplusplus.com/reference/algorithm/find/
it states that

The function uses operator== to compare the individual elements to val.

and
1
2
3
4
5
6
7
8
9
template<class InputIterator, class T>
  InputIterator find (InputIterator first, InputIterator last, const T& val)
{
  while (first!=last) {
    if (*first==val) return first;
    ++first;
  }
  return last;
}


in my code I have the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person
{
public:
	std::string fName;
	std::string lName;
	int Age;
	Person();
	Person(std::string first_name, std::string last_name, int age)
		:fName(first_name), lName(last_name), Age(age) { }

private:

};
Person::Person(){}

std::vector<Person> List;


now I fill the List vector with People (first, lastname, and age) with
 
List.push_back(Person(fname, lname, age));


and now I want to pull the records, for either, the people of the same age, the people with the same last name, or the people with the same first name.
 
j = std::find(List.begin(), List.end(), nameabc) - List.begin();

should give j a size_t value for the record position in the list where the last name corresponds to the variable nameabc, although I know it can't because I have nowhere pointed it to List[n].lName, and I don't understand how I can accomplish that.
All my searches and tries end up in headache and code I don't understand.

You want http://www.cplusplus.com/reference/algorithm/find_if/

1
2
auto it = std::find_if( List.begin(), List.end(), [](const Person & p){ return 42 == p.Age; } );
if ( List.end() != it ) ...
Thank you keskiverto,

so now, I get the position of the first person in the List that is 42, even though there could be more.

A few additional questions:

1. Is there a possibility to get the rest through the find_if or would I have to go through a loop and compare each entry to pull all the matching records?

2. Can you explain to me, how the compiler knows that const Person & p is the person in the list?
According to the reference of find_if, it is the UnaryPredicate or pred parameter, but how does it work?

While I'm typing this, I'm thinking of the following (not sure if it is correct though):

[](const Person & p) is an unnamed function, that takes the current iterator of the List vector as parameter, and passes it by reference to the function, so *List is actually now p.Age, p.fName, p.lName.

With this I can now compare a value with the contents of whichever class member in the vector.

What are the square brackets [] used for? Is it to pass a variable or something?

Again, thank you for your help! :)
1. One does not simply ... iterate over items without iterating over them.
1
2
3
4
5
6
7
// foo is something suitable
auto it = std::find_if( List.begin(), List.end(), foo );
while ( List.end() != it ) {
  // use the it

  it = std::find_if( it+1, List.end(), foo ); // find next
}

However, the header algorithm has more than just find and find_if:
http://www.cplusplus.com/reference/algorithm/copy_if/
It is a loop!
1
2
3
std::vector<Person> fools;
fools.reserve( List.size() );
std::copy_if( List.begin(), List.end(), fools.begin(), foo );


2. Look at the equivalent of find_if:
1
2
3
4
5
6
7
8
9
template<class InputIterator, class UnaryPredicate>
  InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  while (first!=last) {
    if ( pred( *first ) ) return first;
    ++first;
  }
  return last;
}

- The 'first' is an iterator. (List.begin() is an iterator.)
- The 'pred' is used like it would be a function: name 'pred', a '(', some argument, and ')' -- that is a function call
- The "some argument" is '*first'. unary operator* on iterator is like dereferencing pointer. You access te pointed to object.
- The 'pred()' is used as a conditional expression. It returns bool, or something that can convert to bool.


So what is pred? As a template it can be any type that fulfills the requirements: can be called like a function with one argument (that has iterator's value_type) and returns a bool.

The term "predicate" mean something that returns bool. More generic terms are "functor", "function object" and "function pointer". Predicate is a special type of functor.

In http://www.cplusplus.com/reference/algorithm/sort/
you see both function and struct used as "comp". A class/struct can have operator() so that an object can be used like it were a function. Such object can be "stateful", for example keep count of how many times the op() is called.

The []( /*args*/ ){ /*body*/ } is indeed an unnamed function. The syntax is for a "lambda function" that was added in C++11. You can probably find more info about it.

Lambda syntax lets you write the function's code where it is used. You can immediately see what 42 == p.Age is seeking without scrolling up / to other file to see what "myfunction" does. Lambda is an exception to the rule that one cannot define a function inside other function.

Lambda can be "stateful".
Thank you for your help and the explanations. Excellent! I'm looking into lambdas now.
Topic archived. No new replies allowed.