std::find and std::find_if algorithms are used to find first element in the given range.

In this article we will see how to use std::find and std::find_if algorithm with user defined datatypes i.e. Classes & Structures.

Internally std::find algorithm uses the == operator for comparisons. For built-in data types like int, std::string etc operator == is by default available but for user defined data types i.e classes & struct we need to define == operator.

Lets learn by example,

Suppose we have a list of class Item objects. Each item object has a properties like Id, price and availability count. Now we want to search for an item object with specific ID from this vector.

How to do it?

We will do it using std::find algorithm. Lets first see the Item class,

As std::find uses the == operator for comparision, therefore we have define opeartor == in the Item class.

Lets search for the Item object with Id “126”,

As we have hard coded the comparison logic of two Item objects in operator == i.e. based on the Id.
So, what if we need to search for the Item object with specific price, we can not use the == operator for it. How to do it?

Here comes the std::find_if algorithm in picture,


std::find_if finds first element in the given range based on the custom comparator passed. For example,

Lets first create a comparator function,

Now use this comparator with std::find_if algorithm,

But what if we need to search Item object based on count ? Then based on above approach we need to create a different comparator function for it. So, what can we do to improve it?

Lets create a Generic Comparator functor for searching based on any property of a class,

Lets use std::find_if with this generic comparator functor,

Lets improve this more,

What if we don’t want to define this Generic Comparator functor, the how we can find Item object easily with std::find_if ?

Its using lambda functions,

Happy Coding 🙂

Complete executable Code is as follows,


#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <algorithm>
#include <functional>

class Item
{
private:
	std::string  m_ItemId;
	int m_Price;
	int m_Count;
public:
	Item(std::string id, int price, int count):
		m_ItemId(id), m_Count(count), m_Price(price)
	{}
	int getCount() const {
		return m_Count;
	}
	std::string getItemId() const {
		return m_ItemId;
	}
	int getPrice() const {
		return m_Price;
	}
	bool operator==(const Item & obj2) const
	{
		if(this->getItemId().compare(obj2.getItemId()) == 0)
			return true;
		else
			return false;
	}
};


std::vector<Item> getItemList()
{
	std::vector<Item> vecOfItems ;
	vecOfItems.push_back(Item("D121",100,2));
	vecOfItems.push_back(Item("D122",12,5));
	vecOfItems.push_back(Item("D123",28,6));
	vecOfItems.push_back(Item("D124",8,10));
	vecOfItems.push_back(Item("D125",99,3));
	return vecOfItems;
}

bool priceComparision(Item & obj, int y)
{
	if(obj.getPrice() == y)
		return true;
	else
		return false;
}


template <typename T>
struct GenericComparator
{
	typedef  int (T::*GETTER)() const;
	GETTER m_getterFunc;
	int m_data;
	GenericComparator(GETTER getterFunc, int data)
	{
		m_getterFunc = getterFunc;
		m_data = data;
	}
	bool operator()(const Item  & obj)
	{
		if((obj.*m_getterFunc)() == m_data)
			return true;
		else
			return false;
	}
};


bool IsLesser10 (int i) {
  return (i < 10);
}

int main()
{

	std::vector<int> vecData{1,2,3,4,5};

	std::vector<int>::iterator it1;
	it1 = std::find(vecData.begin(), vecData.end(), 2);
	if(it1 != vecData.end())
		std::cout<<*it1<<std::endl;
	it1 = std::find_if(vecData.begin(), vecData.end(), IsLesser10 );
	if(it1 != vecData.end())
		std::cout<<*it1<<std::endl;


	std::vector<Item> vecOfItems = getItemList();
	std::vector<Item>::iterator it = std::find(vecOfItems.begin(), vecOfItems.end(), Item("D126",99,0));

	if(it != vecOfItems.end())
		std::cout<<"Found with ID :: "<<it->getItemId()<< " Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
	else
		std::cout<<"Item with ID :: D126 not Found"<<std::endl;

	it = std::find(vecOfItems.begin(), vecOfItems.end(), Item("D124",99,0));
	if(it != vecOfItems.end())
		std::cout<<"Found with ID :: "<<it->getItemId()<< " Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
	else
		std::cout<<"Item with ID :: D124 not Found"<<std::endl;



	it = std::find_if(vecOfItems.begin(), vecOfItems.end(), [](Item const& obj){
																			return obj.getPrice() == 28;
																		} );

	if(it != vecOfItems.end())
		std::cout<<"Found with ID :: "<<it->getItemId()<< " Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
	else
		std::cout<<"Item not Found"<<std::endl;



		it = std::find_if(vecOfItems.begin(), vecOfItems.end(), std::bind(priceComparision,  std::placeholders::_1 , 28) );
		if(it != vecOfItems.end())
			std::cout<<"Found with ID :: "<<it->getItemId()<< " Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
		else
			std::cout<<"Item not Found"<<std::endl;



	it = std::find_if(vecOfItems.begin(), vecOfItems.end(),  GenericComparator<Item>(&Item::getPrice, 99)   );
	if(it != vecOfItems.end())
		std::cout<<"Found with ID :: "<<it->getItemId()<< " Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
	else
		std::cout<<"Item not Found"<<std::endl;


	return 0;
}

Click Here to Subscribe for more Articles / Tutorials like this.