Create Set of User Defined Class in C++

In this article we will see how to use std::set with user defined classes.

If you want to use std::set with user defined classes and use default sorting criteria then overload operator < in the class.

For example,

Suppose our class is Message that contains three properties i.e.
• Member content
• Sending User Name
• Receiving User Name

And to use this class objects in std::set with default sorting criteria we need to overload operator <.

Let’s see Message Class



    #include<iostream>
    #include<set>
    #include<string>
    
    class Message
    {
    public:
    	std::string m_MsgContent;
    	std::string m_sentBy;
    	std::string m_recivedBy;
    
    	Message(std::string sentBy, std::string recBy, std::string msg) :
    		m_MsgContent(msg), m_sentBy(sentBy), m_recivedBy(recBy)
    	{}
    
    	bool operator< (const Message & msgObj) const
    	{
    		std::string rightStr = 	msgObj.m_MsgContent + msgObj.m_sentBy + msgObj.m_recivedBy;
    		std::string leftStr = 	this->m_MsgContent + this->m_sentBy + this->m_recivedBy;
    		return (leftStr < rightStr);
    	}
    	friend std::ostream& operator<<(std::ostream& os, const Message& obj);
    
    };
    std::ostream& operator<<(std::ostream& os, const Message& obj)
    {
    	os<<obj.m_sentBy<<" :: "<<obj.m_MsgContent<<" :: "<<obj.m_recivedBy<<std::endl;
    	return os;
    }
    

    According to above implementation of operator < function, two Message objects are compared on the bases of all the 3 properties.

    So suppose we created 4 Message objects,

    Message msg1("user_1", "Hello", "user_2");
    Message msg2("user_1", "Hello", "user_3");
    Message msg3("user_3", "Hello", "user_1");
    Message msg4("user_1", "Hello", "user_3");
    

    Here msg2 and msg4 are equal because

    msg2 < msg4 is false AND msg4 < msg2 is false.

    So, std::set will also treat msg4 as duplicate of msg2 as per current default sorting criteria i.e. operator <.

    Now Let’s use this class in std::set,

    int main()
    {
    	std::set<Message> setOfMsgs;
    
    	Message msg1("user_1", "Hello", "user_2");
    	Message msg2("user_1", "Hello", "user_3");
    	Message msg3("user_3", "Hello", "user_1");
    	// A Duplicate Message
    	Message msg4("user_1", "Hello", "user_3");
    
    	setOfMsgs.insert(msg1);
    	setOfMsgs.insert(msg2);
    	setOfMsgs.insert(msg3);
    	setOfMsgs.insert(msg4);
    
    	// msg4 will not get inserted because its duplicate as per the current operator < implementation.
    
    	// Iterate through all the elements in a set and display the value.
    		for (std::set<Message>::iterator it=setOfMsgs.begin(); it!=setOfMsgs.end(); ++it)
    		    std::cout << *it ;
    
    	return 0;
    }
    
    

    Output:
    user_3 :: user_1 :: Hello
    user_1 :: user_2 :: Hello
    user_1 :: user_3 :: Hello

    But What if we enhance our requirement i.e.
    Now we want to keep only single message sent by each user i.e. only one sent message is allowed per user. Then what ??

    Option 1 :
    Modify operator <, but then it can hamper our previous requirements and it might be possible that we don’t have write access to operator <.

    Option 2:
    Create a new set and use an external soring criteria i.e Comparator. We will discuss this in next article.

    Scroll to Top