C++ : Map Tutorial Part 3: Using User defined class objects as keys in std::map

In the previous article, we have discussed about C++ Map : Operator [] – Usage Details. Let us learn Map Tutorial in C++ Program.

Using User defined class objects as keys in std::map

In this article, we are going to see how we can use user defined class objects as keys in the std::map.

The std::map by default uses the < operator to sort the keys however it is not available for user defined classes.

So, for the user defined classes we should have a default sorting criteria or we need a comparator that can compare two objects.

Overloading operator < for sorting of keys :

We are going to overload the operator < demonstrate by the following example

#include <iostream>
#include <map>
#include <string>
class User
{
    std::string m_identity;
    std::string m_text;

public:
    User(std::string text, std::string identity)
        : m_identity(identity), m_text(text)
    {
    }
    const std::string &getId() const
    {
        return m_identity;
    }
    const std::string &getText() const
    {
        return m_text;
    }
    bool operator<(const User &userObj) const
    {
        if (userObj.m_identity < this->m_identity)
            return true;
    }
};
//Method that sets the Class as key
void example_1()
{
    std::map<User, int> m_userInMap;
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.A", "3"), 100));
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.B", "1"), 102));
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.A", "2"), 109));
    std::map<User, int>::iterator it = m_userInMap.begin();
    for (; it != m_userInMap.end(); it++)
    {
        std::cout << it->first.getText() << " :: " << it->second << std::endl;
    }
}

int main()
{
    std::cout << "EX 1 :: Comparing ID" << std::endl;
    example_1();
    return 0;
}

Output :

EX 1 :: Comparing ID

Mr.A :: 100

Mr.A :: 109

Mr.B :: 102

In the above example we can see two objects of the user defined class and one duplicate as we assigned two values to the same key i.e. Mr. A.

In case we want to change the sorting criteria for the keys, we can either modify the definition of the operator < or we can use external comparators.

Using Comparator for sorting of keys :

#include <iostream>
#include <map>
#include <string>
class User
{
    std::string m_identity;
    std::string m_text;

public:
    User(std::string text, std::string identity)
        : m_identity(identity), m_text(text)
    {
    }
    const std::string &getId() const
    {
        return m_identity;
    }
    const std::string &getText() const
    {
        return m_text;
    }
    bool operator<(const User &userObj) const
    {
        if (userObj.m_identity < this->m_identity)
            return true;
    }
};
struct UserNameComparator
{
    bool operator()(const User &left, const User &right) const
    {
        return (left.getText() > right.getText());
    }
};
void example_1()
{
    std::map<User, int, UserNameComparator> m_userInMap;
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.A", "3"), 100));
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.B", "1"), 102));
    m_userInMap.insert(std::make_pair<User, int>(User("Mr.A", "2"), 109));
    std::map<User, int, UserNameComparator>::iterator it = m_userInMap.begin();
    for (; it != m_userInMap.end(); it++)
    {
        std::cout << it->first.getText() << " :: " << it->second << std::endl;
    }
}

int main()
{
    std::cout << "EX 1 :: Comparing ID" << std::endl;
    example_1();
    return 0;
}
Output:

EX 1 :: Comparing ID

Mr.B :: 102

Mr.A :: 100

Here we get only one entry for the Mr.A as we used the User objects to compare keys.