Using std::find & std::find_if with User Defined Classes | CPP std::find_if with lambda | std::find & std::find_if Examples

In this article, we will be going to discuss how to use std::find and std::find_if algorithm with User Defined Classes.

Using std::find & std::find_if with User Defined Classes

Generally for built-in datatypes like int,string etc ‘std::find’ algorithm uses “==” operator for comparisons but for user defined data types i.e classes & structure we need to define “==” operator.

Now we will take some example,

Let’s take a list of class Item objects. Each of them has properties like Id, price, and availability count.

Now we want to search for an item object with a specific ID from this vector. So let’s see how we will do it,

With std::find

We will do it using the ‘std::find’ algorithm.

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

Above we see that ‘std::find’ uses the ‘==’ operator for comparison, therefore we have to define operator == in the Item class.

Let’s search for the Item object with Id “126”,

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

So in the above algorithm, you can see that we tried to find ‘id=126’ but we were not able to found because there is no id like that.

Above you have seen how to use ‘std::find ‘ now if we need to search for the Item object with a specific price, we can not use the == operator for it. Hence, we will use the ‘std::find_if’ algorithm.

Also Check:

Create a Comparator Function

Let’s first create a comparator function, because ‘std::find_if’ finds the first element in the given range based on the custom comparator passed.

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

With std::find_if

Now we will use this comparator with std::find_if algorithm,

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

So, if we want to search Item objects based on count we use the below algorithm.

Creation of Generic Comparator Function

Let’s create a Generic Comparator function for searching based on any property of a class,

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 T  & obj)
    {
        if((obj.*m_getterFunc)() == m_data)
            return true;
        else
            return false;
    }
};

Lets use ‘std::find_if with this generic comparator function,

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

std: :find_if with lambda

If you want to make some improvement in the above coding like if we don’t want to define this Generic Comparator function then, we will use lambda functions,

std::vector<Item> vecOfItems = getItemList();
std::vector<Item>::iterator it;
it = std::find_if(vecOfItems.begin(), vecOfItems.end(), [](Item const& obj){
        return obj.getPrice() == 28;
    } );
if(it != vecOfItems.end())
    std::cout<<"Item Price ::"<<it->getPrice()<<" Count :: "<<it->getCount()<<std::endl;
else
    std::cout<<"Item not Found"<<std::endl;

Now we are going to show the complete code in one go, so you can see how it is working.

#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;
}

Output:

Item with ID :: D126 not Found
Found with ID :: D124 Price ::8 Count :: 10
Found with ID :: D123 Price ::28 Count :: 6
Found with ID :: D123 Price ::28 Count :: 6
Found with ID :: D125 Price ::99 Count :: 3

Conclusion:

In this article, you have seen how to use the ‘std::find’ and ‘std::find_if’ algorithms with User Defined Classes. Thank you!