std::set example – C++ std::set Example and Tutorial with User Defined Classes

std::set example: In the previous article, we have discussed about How to Iterate over a map in C++. Let us learn about std::set Example and Tutorial with User Defined Classes in C++ Program.

std::set Example and Tutorial

C++ std set example: In this article, we will learn to use std::set with user defined classes.

We will overload operator < in the class to use std::set with user defined classes and also to implement default sorting criteria.

Let our class is MsgInfo which contains the following three properties,

  1. Message content
  2. Message sender
  3. Message receiver
#include<iostream>
#include<set>
#include<string>
class MsgInfo
{
public:
    std::string msgCont;
    std::string msgSender;
    std::string msgReceiver;
    MsgInfo(std::string sender, std::string receiver, std::string msg) :
        msgCont(msg), msgSender(sender), msgReceiver(receiver)
    {}
    bool operator< (const MsgInfo & msgOb) const
    {
        std::string rightStr =     msgOb.msgCont + msgOb.msgSender + msgOb.msgReceiver;
        std::string leftStr =     this->msgCont + this->msgSender + this->msgReceiver;
        return (leftStr < rightStr);
    }
    friend std::ostream& operator<<(std::ostream& os, const MsgInfo& obj);
};
std::ostream& operator<<(std::ostream& os, const MsgInfo& obj)
{
    os<<obj.msgSender<<" :: "<<obj.msgCont<<" :: "<<obj.msgReceiver<<std::endl;
    return os;
}

According to the implementation of < operator in above, two MsgInfo objects will be compared based on all three properties. Let’s create 4 MsgInfo objects,

MsgInfo msg1("persA", "Hi!", "persB");

MsgInfo msg2("persA", "Hi!", "persC");

MsgInfo msg3("persC", "Hi!", "persA");

MsgInfo msg4("persA", "Hi!", "persC");

Since msg2<msg4 and msg4<msg2 both are false so msg2 and msg4 are equal. So as per current default sorting criteria i.e. operator <, std::set will treat msg4 as a duplicate of msg2.

int main()
{
    std::set<MsgInfo> setOfMsgs;
    MsgInfo msg1("persA", "Hi!", "persB");
    MsgInfo msg2("persA", "Hi!", "persC");
    MsgInfo msg3("persC", "Hi!", "persA");
    // Duplicate Message
    MsgInfo msg4("persA", "Hi!", "persC");
    
    setOfMsgs.insert(msg1);
    setOfMsgs.insert(msg2);
    setOfMsgs.insert(msg3);
    setOfMsgs.insert(msg4);
    // As msg4 will be treated as duplicate so it wil not be inserted
    // Iterate through the elements then set and display the values
        for (std::set<MsgInfo>::iterator iter=setOfMsgs.begin(); iter!=setOfMsgs.end(); ++iter)
            std::cout << *iter ;
    return 0;
}

We can also keep only one message allowed per person by twp methods.

Method 1: Modify operator <, but it may hamper our previous requirements and we may don’t require to access that the operator <.

Method 2: We can form a new set and use Comparator which is a external sorting criteria.

Complete Program :

#include<iostream>
#include<set>
#include<string>
class MsgInfo
{
public:
    std::string msgCont;
    std::string msgSender;
    std::string msgReceiver;
    MsgInfo(std::string sender, std::string receiver, std::string msg) :
        msgCont(msg), msgSender(sender), msgReceiver(receiver)
    {}
    bool operator< (const MsgInfo & msgOb) const
    {
        std::string rightStr =     msgOb.msgCont + msgOb.msgSender + msgOb.msgReceiver;
        std::string leftStr =     this->msgCont + this->msgSender + this->msgReceiver;
        return (leftStr < rightStr);
    }
    friend std::ostream& operator<<(std::ostream& os, const MsgInfo& obj);
};
std::ostream& operator<<(std::ostream& os, const MsgInfo& obj)
{
    os<<obj.msgSender<<" :: "<<obj.msgCont<<" :: "<<obj.msgReceiver<<std::endl;
    return os;
}


int main()
{
    std::set<MsgInfo> setOfMsgs;
    MsgInfo msg1("persA", "Hi!", "persB");
    MsgInfo msg2("persA", "Hi!", "persC");
    MsgInfo msg3("persC", "Hi!", "persA");
    // Duplicate Message
    MsgInfo msg4("persA", "Hi!", "persC");
    
    setOfMsgs.insert(msg1);
    setOfMsgs.insert(msg2);
    setOfMsgs.insert(msg3);
    setOfMsgs.insert(msg4);
    // msg4 will be treated as duplicate so it will not be inserted
    // iterate through the elements then set and display the values
        for (std::set<MsgInfo>::iterator iter=setOfMsgs.begin(); iter!=setOfMsgs.end(); ++iter)
            std::cout << *iter ;
    return 0;
}

Output :

persC :: persA :: Hi!
persA :: persB :: Hi!
persA :: persC :: Hi!